rocket_community/response/
response.rs

1use std::borrow::Cow;
2use std::collections::HashMap;
3use std::{fmt, str};
4
5use tokio::io::{AsyncRead, AsyncSeek};
6
7use crate::data::IoHandler;
8use crate::http::uncased::{AsUncased, Uncased};
9use crate::http::{ContentType, Cookie, Header, HeaderMap, Status};
10use crate::response::Body;
11
12/// Builder for the [`Response`] type.
13///
14/// Building a [`Response`] can be a low-level ordeal; this structure presents a
15/// higher-level API that simplifies building `Response`s.
16///
17/// # Usage
18///
19/// `Builder` follows the builder pattern and is usually obtained by calling
20/// [`Response::build()`] on `Response`. Almost all methods take the current
21/// builder as a mutable reference and return the same mutable reference with
22/// field(s) modified in the `Response` being built. These method calls can be
23/// chained: `build.a().b()`.
24///
25/// To finish building and retrieve the built `Response`, use the
26/// [`finalize()`](#method.finalize) or [`ok()`](#method.ok) methods.
27///
28/// ## Headers
29///
30/// When building a `Response`, headers can either be _replaced_ or _adjoined_;
31/// the default behavior (using `header(..)`) is to _replace_. When a header is
32/// _replaced_, any existing values for headers with the same name are removed,
33/// and the new value is set. If no header exists, the header is simply added.
34/// On the other hand, when a header is _adjoined_, all existing values will
35/// remain, and the `value` of the adjoined header will be added to the set of
36/// existing values, if any. Adjoining maintains order: headers adjoined first
37/// will appear first in the `Response`.
38///
39/// ## Joining and Merging
40///
41/// It is often necessary to combine multiple `Response`s in some way. The
42/// [merge](#method.merge) and [join](#method.join) methods facilitate this. The
43/// `merge` method replaces all of the fields in `self` with those present in
44/// `other`. The `join` method sets any fields not set in `self` to the value in
45/// `other`. See their documentation for more details.
46/// ## Example
47///
48/// The following example builds a `Response` with:
49///
50///   * **Status**: `418 I'm a teapot`
51///   * **Content-Type** header: `text/plain; charset=utf-8`
52///   * **X-Teapot-Make** header: `Rocket`
53///   * **X-Teapot-Model** headers: `Utopia`, `Series 1`
54///   * **Body**: fixed-size string `"Brewing the best coffee!"`
55///
56/// ```rust
57/// # extern crate rocket_community as rocket;
58/// use std::io::Cursor;
59/// use rocket::response::Response;
60/// use rocket::http::{Status, ContentType};
61///
62/// let body = "Brewing the best coffee!";
63/// let response = Response::build()
64///     .status(Status::ImATeapot)
65///     .header(ContentType::Plain)
66///     .raw_header("X-Teapot-Make", "Rocket")
67///     .raw_header("X-Teapot-Model", "Utopia")
68///     .raw_header_adjoin("X-Teapot-Model", "Series 1")
69///     .sized_body(body.len(), Cursor::new(body))
70///     .finalize();
71/// ```
72pub struct Builder<'r> {
73    response: Response<'r>,
74}
75
76impl<'r> Builder<'r> {
77    /// Creates a new `Builder` that will build on top of the `base`
78    /// `Response`.
79    ///
80    /// # Example
81    ///
82    /// ```rust
83    /// # extern crate rocket_community as rocket;
84    /// use rocket::response::{Builder, Response};
85    ///
86    /// # #[allow(unused_variables)]
87    /// let builder = Builder::new(Response::new());
88    /// ```
89    #[inline(always)]
90    pub fn new(base: Response<'r>) -> Builder<'r> {
91        Builder { response: base }
92    }
93
94    /// Sets the status of the `Response` being built to `status`.
95    ///
96    /// # Example
97    ///
98    /// ```rust
99    /// # extern crate rocket_community as rocket;
100    /// use rocket::Response;
101    /// use rocket::http::Status;
102    ///
103    /// let response = Response::build()
104    ///     .status(Status::NotFound)
105    ///     .finalize();
106    /// ```
107    #[inline(always)]
108    pub fn status(&mut self, status: Status) -> &mut Builder<'r> {
109        self.response.set_status(status);
110        self
111    }
112
113    /// Adds `header` to the `Response`, replacing any header with the same name
114    /// that already exists in the response. If multiple headers with
115    /// the same name exist, they are all removed, and only the new header and
116    /// value will remain.
117    ///
118    /// The type of `header` can be any type that implements `Into<Header>`. See
119    /// [trait implementations](Header#trait-implementations).
120    ///
121    /// # Example
122    ///
123    /// ```rust
124    /// # extern crate rocket_community as rocket;
125    /// use rocket::Response;
126    /// use rocket::http::ContentType;
127    ///
128    /// let response = Response::build()
129    ///     .header(ContentType::JSON)
130    ///     .header(ContentType::HTML)
131    ///     .finalize();
132    ///
133    /// assert_eq!(response.headers().get("Content-Type").count(), 1);
134    /// ```
135    #[inline(always)]
136    pub fn header<'h: 'r, H>(&mut self, header: H) -> &mut Builder<'r>
137    where
138        H: Into<Header<'h>>,
139    {
140        self.response.set_header(header);
141        self
142    }
143
144    /// Adds `header` to the `Response` by adjoining the header with any
145    /// existing headers with the same name that already exist in the
146    /// `Response`. This allows for multiple headers with the same name and
147    /// potentially different values to be present in the `Response`.
148    ///
149    /// The type of `header` can be any type that implements `Into<Header>`. See
150    /// [trait implementations](Header#trait-implementations).
151    ///
152    /// # Example
153    ///
154    /// ```rust
155    /// # extern crate rocket_community as rocket;
156    /// use rocket::Response;
157    /// use rocket::http::{Header, Accept};
158    ///
159    /// let response = Response::build()
160    ///     .header_adjoin(Header::new("Accept", "application/json"))
161    ///     .header_adjoin(Accept::XML)
162    ///     .finalize();
163    ///
164    /// assert_eq!(response.headers().get("Accept").count(), 2);
165    /// ```
166    #[inline(always)]
167    pub fn header_adjoin<'h: 'r, H>(&mut self, header: H) -> &mut Builder<'r>
168    where
169        H: Into<Header<'h>>,
170    {
171        self.response.adjoin_header(header);
172        self
173    }
174
175    /// Adds a custom header to the `Response` with the given name and value,
176    /// replacing any header with the same name that already exists in the
177    /// response. If multiple headers with the same name exist, they are all
178    /// removed, and only the new header and value will remain.
179    ///
180    /// # Example
181    ///
182    /// ```rust
183    /// # extern crate rocket_community as rocket;
184    /// use rocket::Response;
185    ///
186    /// let response = Response::build()
187    ///     .raw_header("X-Custom", "first")
188    ///     .raw_header("X-Custom", "second")
189    ///     .finalize();
190    ///
191    /// assert_eq!(response.headers().get("X-Custom").count(), 1);
192    /// ```
193    #[inline(always)]
194    pub fn raw_header<'a, 'b, N, V>(&mut self, name: N, value: V) -> &mut Builder<'r>
195    where
196        N: Into<Cow<'a, str>>,
197        V: Into<Cow<'b, str>>,
198        'a: 'r,
199        'b: 'r,
200    {
201        self.response.set_raw_header(name, value);
202        self
203    }
204
205    /// Adds custom header to the `Response` with the given name and value,
206    /// adjoining the header with any existing headers with the same name that
207    /// already exist in the `Response`. This allows for multiple headers with
208    /// the same name and potentially different values to be present in the
209    /// `Response`.
210    ///
211    /// # Example
212    ///
213    /// ```rust
214    /// # extern crate rocket_community as rocket;
215    /// use rocket::Response;
216    ///
217    /// let response = Response::build()
218    ///     .raw_header_adjoin("X-Custom", "first")
219    ///     .raw_header_adjoin("X-Custom", "second")
220    ///     .finalize();
221    ///
222    /// assert_eq!(response.headers().get("X-Custom").count(), 2);
223    /// ```
224    #[inline(always)]
225    pub fn raw_header_adjoin<'a, 'b, N, V>(&mut self, name: N, value: V) -> &mut Builder<'r>
226    where
227        N: Into<Cow<'a, str>>,
228        V: Into<Cow<'b, str>>,
229        'a: 'r,
230        'b: 'r,
231    {
232        self.response.adjoin_raw_header(name, value);
233        self
234    }
235
236    /// Sets the body of the `Response` to be the fixed-sized `body` with size
237    /// `size`, which may be `None`. If `size` is `None`, the body's size will
238    /// be computed with calls to `seek` when the response is written out.
239    ///
240    /// # Example
241    ///
242    /// ```rust
243    /// # extern crate rocket_community as rocket;
244    /// use std::io::Cursor;
245    /// use rocket::Response;
246    ///
247    /// let body = "Hello, world!";
248    /// let response = Response::build()
249    ///     .sized_body(body.len(), Cursor::new(body))
250    ///     .finalize();
251    /// ```
252    pub fn sized_body<B, S>(&mut self, size: S, body: B) -> &mut Builder<'r>
253    where
254        B: AsyncRead + AsyncSeek + Send + 'r,
255        S: Into<Option<usize>>,
256    {
257        self.response.set_sized_body(size, body);
258        self
259    }
260
261    /// Sets the body of the `Response` to be the streamed `body`.
262    ///
263    /// # Example
264    ///
265    /// ```rust
266    /// # extern crate rocket_community as rocket;
267    /// use std::io::Cursor;
268    /// use rocket::Response;
269    ///
270    /// let response = Response::build()
271    ///     .streamed_body(Cursor::new("Hello, world!"))
272    ///     .finalize();
273    /// ```
274    #[inline(always)]
275    pub fn streamed_body<B>(&mut self, body: B) -> &mut Builder<'r>
276    where
277        B: AsyncRead + Send + 'r,
278    {
279        self.response.set_streamed_body(body);
280        self
281    }
282
283    /// Registers `handler` as the I/O handler for upgrade protocol `protocol`.
284    ///
285    /// This is equivalent to [`Response::add_upgrade()`].
286    ///
287    /// **NOTE**: Responses registering I/O handlers for upgraded protocols
288    /// **should not** set the response status to `101 Switching Protocols`, nor set the
289    /// `Connection` or `Upgrade` headers. Rocket automatically sets these
290    /// headers as needed. See [`Response`#upgrading] for details.
291    ///
292    /// # Example
293    ///
294    /// ```rust
295    /// # extern crate rocket_community as rocket;
296    /// use std::pin::Pin;
297    ///
298    /// use rocket::Response;
299    /// use rocket::data::{IoHandler, IoStream};
300    /// use rocket::tokio::io;
301    ///
302    /// struct EchoHandler;
303    ///
304    /// #[rocket::async_trait]
305    /// impl IoHandler for EchoHandler {
306    ///     async fn io(self: Box<Self>, io: IoStream) -> io::Result<()> {
307    ///         let (mut reader, mut writer) = io::split(io);
308    ///         io::copy(&mut reader, &mut writer).await?;
309    ///         Ok(())
310    ///     }
311    /// }
312    ///
313    /// let response = Response::build()
314    ///     .upgrade("raw-echo", EchoHandler)
315    ///     .streamed_body(std::io::Cursor::new("We didn't upgrade!"))
316    ///     .finalize();
317    /// ```
318    #[inline(always)]
319    pub fn upgrade<P, H>(&mut self, protocol: P, handler: H) -> &mut Builder<'r>
320    where
321        P: Into<Uncased<'r>>,
322        H: IoHandler + 'r,
323    {
324        self.response.add_upgrade(protocol.into(), handler);
325        self
326    }
327
328    /// Sets the max chunk size of a body, if any, to `size`.
329    ///
330    /// See [`Response::set_max_chunk_size()`] for notes.
331    ///
332    /// # Example
333    ///
334    /// ```rust
335    /// # extern crate rocket_community as rocket;
336    /// use std::io::Cursor;
337    /// use rocket::Response;
338    ///
339    /// let response = Response::build()
340    ///     .streamed_body(Cursor::new("Hello, world!"))
341    ///     .max_chunk_size(3072)
342    ///     .finalize();
343    /// ```
344    #[inline(always)]
345    pub fn max_chunk_size(&mut self, size: usize) -> &mut Builder<'r> {
346        self.response.set_max_chunk_size(size);
347        self
348    }
349
350    /// Merges the `other` `Response` into `self` by setting any fields in
351    /// `self` to the corresponding value in `other` if they are set in `other`.
352    /// Fields in `self` are unchanged if they are not set in `other`. If a
353    /// header is set in both `self` and `other`, the values in `other` are
354    /// kept. Headers set only in `self` remain.
355    ///
356    /// # Example
357    ///
358    /// ```rust
359    /// # extern crate rocket_community as rocket;
360    /// use rocket::Response;
361    /// use rocket::http::{Status, ContentType};
362    ///
363    /// let base = Response::build()
364    ///     .status(Status::NotFound)
365    ///     .header(ContentType::HTML)
366    ///     .raw_header("X-Custom", "value 1")
367    ///     .finalize();
368    ///
369    /// let response = Response::build()
370    ///     .status(Status::ImATeapot)
371    ///     .raw_header("X-Custom", "value 2")
372    ///     .raw_header_adjoin("X-Custom", "value 3")
373    ///     .merge(base)
374    ///     .finalize();
375    ///
376    /// assert_eq!(response.status(), Status::NotFound);
377    ///
378    /// let ctype: Vec<_> = response.headers().get("Content-Type").collect();
379    /// assert_eq!(ctype, vec![ContentType::HTML.to_string()]);
380    ///
381    /// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
382    /// assert_eq!(custom_values, vec!["value 1"]);
383    /// ```
384    #[inline(always)]
385    pub fn merge(&mut self, other: Response<'r>) -> &mut Builder<'r> {
386        self.response.merge(other);
387        self
388    }
389
390    /// Joins the `other` `Response` into `self` by setting any fields in `self`
391    /// to the corresponding value in `other` if they are set in `self`. Fields
392    /// in `self` are unchanged if they are already set. If a header is set in
393    /// both `self` and `other`, the values are adjoined, with the values in
394    /// `self` coming first. Headers only in `self` or `other` are set in
395    /// `self`.
396    ///
397    /// # Example
398    ///
399    /// ```rust
400    /// # extern crate rocket_community as rocket;
401    /// use rocket::Response;
402    /// use rocket::http::{Status, ContentType};
403    ///
404    /// let other = Response::build()
405    ///     .status(Status::NotFound)
406    ///     .header(ContentType::HTML)
407    ///     .raw_header("X-Custom", "value 1")
408    ///     .finalize();
409    ///
410    /// let response = Response::build()
411    ///     .status(Status::ImATeapot)
412    ///     .raw_header("X-Custom", "value 2")
413    ///     .raw_header_adjoin("X-Custom", "value 3")
414    ///     .join(other)
415    ///     .finalize();
416    ///
417    /// assert_eq!(response.status(), Status::ImATeapot);
418    ///
419    /// let ctype: Vec<_> = response.headers().get("Content-Type").collect();
420    /// assert_eq!(ctype, vec![ContentType::HTML.to_string()]);
421    ///
422    /// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
423    /// assert_eq!(custom_values, vec!["value 2", "value 3", "value 1"]);
424    /// ```
425    #[inline(always)]
426    pub fn join(&mut self, other: Response<'r>) -> &mut Builder<'r> {
427        self.response.join(other);
428        self
429    }
430
431    /// Return the `Response` structure that was being built by this builder.
432    /// After calling this method, `self` is cleared and must be rebuilt as if
433    /// from `new()`.
434    ///
435    /// # Example
436    ///
437    /// ```rust
438    /// # extern crate rocket_community as rocket;
439    /// use std::io::Cursor;
440    ///
441    /// use rocket::Response;
442    /// use rocket::http::Status;
443    ///
444    /// let body = "Brewing the best coffee!";
445    /// let response = Response::build()
446    ///     .status(Status::ImATeapot)
447    ///     .sized_body(body.len(), Cursor::new(body))
448    ///     .raw_header("X-Custom", "value 2")
449    ///     .finalize();
450    /// ```
451    pub fn finalize(&mut self) -> Response<'r> {
452        std::mem::replace(&mut self.response, Response::new())
453    }
454
455    /// Retrieve the built `Response` wrapped in `Ok`. After calling this
456    /// method, `self` is cleared and must be rebuilt as if from `new()`.
457    ///
458    /// # Example
459    ///
460    /// ```rust
461    /// # extern crate rocket_community as rocket;
462    /// use rocket::Response;
463    ///
464    /// let response: Result<Response, ()> = Response::build()
465    ///     // build the response
466    ///     .ok();
467    ///
468    /// assert!(response.is_ok());
469    /// ```
470    #[inline(always)]
471    pub fn ok<E>(&mut self) -> Result<Response<'r>, E> {
472        Ok(self.finalize())
473    }
474}
475
476/// A response, as returned by types implementing
477/// [`Responder`](crate::response::Responder).
478///
479/// See [`Builder`] for docs on how a `Response` is typically created and the
480/// [module docs](crate::response) for notes on composing responses
481///
482/// ## Upgrading
483///
484/// A response may optionally register [`IoHandler`]s for upgraded requests via
485/// [`Response::add_upgrade()`] or the corresponding builder method
486/// [`Builder::upgrade()`]. If the incoming request 1) requests an upgrade via a
487/// `Connection: Upgrade` header _and_ 2) includes a protocol in its `Upgrade`
488/// header that is registered by the returned `Response`, the connection will be
489/// upgraded. An upgrade response is sent to the client, and the registered
490/// `IoHandler` for the client's preferred protocol is invoked with an
491/// [`IoStream`](crate::data::IoStream) representing a raw byte stream to the
492/// client. Note that protocol names are treated case-insensitively during
493/// matching.
494///
495/// If a connection is upgraded, Rocket automatically set the following in the
496/// upgrade response:
497///   * The response status to `101 Switching Protocols`.
498///   * The `Connection: Upgrade` header.
499///   * The `Upgrade` header's value to the selected protocol.
500///
501/// As such, a response **should never** set a `101` status nor the `Connection`
502/// or `Upgrade` headers: Rocket handles this automatically. Instead, it should
503/// set a status and headers to use in case the connection is not upgraded,
504/// either due to an error or because the client did not request an upgrade.
505///
506/// If a connection _is not_ upgraded due to an error, even though there was a
507/// matching, registered protocol, the `IoHandler` is not invoked, and the
508/// original response is sent to the client without alteration.
509#[derive(Default)]
510pub struct Response<'r> {
511    status: Option<Status>,
512    headers: HeaderMap<'r>,
513    body: Body<'r>,
514    upgrade: HashMap<Uncased<'r>, Box<dyn IoHandler + 'r>>,
515}
516
517impl<'r> Response<'r> {
518    /// Creates a new, empty `Response` without a status, body, or headers.
519    /// Because all HTTP responses must have a status, if a default `Response`
520    /// is written to the client without a status, the status defaults to `200
521    /// Ok`.
522    ///
523    /// # Example
524    ///
525    /// ```rust
526    /// # extern crate rocket_community as rocket;
527    /// use rocket::Response;
528    /// use rocket::http::Status;
529    ///
530    /// let mut response = Response::new();
531    ///
532    /// assert_eq!(response.status(), Status::Ok);
533    /// assert_eq!(response.headers().len(), 0);
534    /// assert!(response.body().is_none());
535    /// ```
536    #[inline(always)]
537    pub fn new() -> Response<'r> {
538        Response::default()
539    }
540
541    /// Returns a `Builder` with a base of `Response::new()`.
542    ///
543    /// # Example
544    ///
545    /// ```rust
546    /// # extern crate rocket_community as rocket;
547    /// use rocket::Response;
548    ///
549    /// # #[allow(unused_variables)]
550    /// let builder = Response::build();
551    /// ```
552    #[inline(always)]
553    pub fn build() -> Builder<'r> {
554        Response::build_from(Response::new())
555    }
556
557    /// Returns a `Builder` with a base of `other`.
558    ///
559    /// # Example
560    ///
561    /// ```rust
562    /// # extern crate rocket_community as rocket;
563    /// # #![allow(unused_variables)]
564    /// use rocket::Response;
565    ///
566    /// let other = Response::new();
567    /// let builder = Response::build_from(other);
568    /// ```
569    #[inline(always)]
570    pub fn build_from(other: Response<'r>) -> Builder<'r> {
571        Builder::new(other)
572    }
573
574    /// Returns the status of `self`.
575    ///
576    /// # Example
577    ///
578    /// ```rust
579    /// # extern crate rocket_community as rocket;
580    /// use rocket::Response;
581    /// use rocket::http::Status;
582    ///
583    /// let mut response = Response::new();
584    /// assert_eq!(response.status(), Status::Ok);
585    ///
586    /// response.set_status(Status::NotFound);
587    /// assert_eq!(response.status(), Status::NotFound);
588    /// ```
589    #[inline(always)]
590    pub fn status(&self) -> Status {
591        self.status.unwrap_or(Status::Ok)
592    }
593
594    /// Sets the status of `self` to `status`.
595    ///
596    /// # Example
597    ///
598    /// ```rust
599    /// # extern crate rocket_community as rocket;
600    /// use rocket::Response;
601    /// use rocket::http::Status;
602    ///
603    /// let mut response = Response::new();
604    /// response.set_status(Status::ImATeapot);
605    /// assert_eq!(response.status(), Status::ImATeapot);
606    /// ```
607    #[inline(always)]
608    pub fn set_status(&mut self, status: Status) {
609        self.status = Some(status);
610    }
611
612    /// Returns the Content-Type header of `self`. If the header is not present
613    /// or is malformed, returns `None`.
614    ///
615    /// # Example
616    ///
617    /// ```rust
618    /// # extern crate rocket_community as rocket;
619    /// use rocket::Response;
620    /// use rocket::http::ContentType;
621    ///
622    /// let mut response = Response::new();
623    /// response.set_header(ContentType::HTML);
624    /// assert_eq!(response.content_type(), Some(ContentType::HTML));
625    /// ```
626    #[inline(always)]
627    pub fn content_type(&self) -> Option<ContentType> {
628        self.headers()
629            .get_one("Content-Type")
630            .and_then(|v| v.parse().ok())
631    }
632
633    /// Returns an iterator over the cookies in `self` as identified by the
634    /// `Set-Cookie` header. Malformed cookies are skipped.
635    ///
636    /// # Example
637    ///
638    /// ```rust
639    /// # extern crate rocket_community as rocket;
640    /// use rocket::Response;
641    /// use rocket::http::Cookie;
642    ///
643    /// let mut response = Response::new();
644    /// response.set_header(Cookie::new("hello", "world!"));
645    /// let cookies: Vec<_> = response.cookies().collect();
646    /// assert_eq!(cookies, vec![Cookie::new("hello", "world!")]);
647    /// ```
648    pub fn cookies(&self) -> impl Iterator<Item = Cookie<'_>> {
649        self.headers()
650            .get("Set-Cookie")
651            .filter_map(|header| Cookie::parse_encoded(header).ok())
652    }
653
654    /// Returns a [`HeaderMap`] of all of the headers in `self`.
655    ///
656    /// # Example
657    ///
658    /// ```rust
659    /// # extern crate rocket_community as rocket;
660    /// use rocket::Response;
661    /// use rocket::http::Header;
662    ///
663    /// let mut response = Response::new();
664    /// response.adjoin_raw_header("X-Custom", "1");
665    /// response.adjoin_raw_header("X-Custom", "2");
666    ///
667    /// let mut custom_headers = response.headers().iter();
668    /// assert_eq!(custom_headers.next(), Some(Header::new("X-Custom", "1")));
669    /// assert_eq!(custom_headers.next(), Some(Header::new("X-Custom", "2")));
670    /// assert_eq!(custom_headers.next(), None);
671    /// ```
672    #[inline(always)]
673    pub fn headers(&self) -> &HeaderMap<'r> {
674        &self.headers
675    }
676
677    pub fn set_header_map<'h: 'r>(&mut self, headers: HeaderMap<'h>) {
678        self.headers = headers;
679    }
680
681    /// Sets the header `header` in `self`. Any existing headers with the name
682    /// `header.name` will be lost, and only `header` will remain. The type of
683    /// `header` can be any type that implements `Into<Header>`. See [trait
684    /// implementations](Header#trait-implementations).
685    ///
686    /// # Example
687    ///
688    /// ```rust
689    /// # extern crate rocket_community as rocket;
690    /// use rocket::Response;
691    /// use rocket::http::ContentType;
692    ///
693    /// let mut response = Response::new();
694    ///
695    /// response.set_header(ContentType::HTML);
696    /// assert_eq!(response.headers().iter().next(), Some(ContentType::HTML.into()));
697    /// assert_eq!(response.headers().len(), 1);
698    ///
699    /// response.set_header(ContentType::JSON);
700    /// assert_eq!(response.headers().iter().next(), Some(ContentType::JSON.into()));
701    /// assert_eq!(response.headers().len(), 1);
702    /// ```
703    #[inline(always)]
704    pub fn set_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) -> bool {
705        self.headers.replace(header)
706    }
707
708    /// Sets the custom header with name `name` and value `value` in `self`. Any
709    /// existing headers with the same `name` will be lost, and the new custom
710    /// header will remain. This method should be used sparingly; prefer to use
711    /// [set_header](#method.set_header) instead.
712    ///
713    /// # Example
714    ///
715    /// ```rust
716    /// # extern crate rocket_community as rocket;
717    /// use rocket::Response;
718    /// use rocket::http::Header;
719    ///
720    /// let mut response = Response::new();
721    ///
722    /// response.set_raw_header("X-Custom", "1");
723    /// assert_eq!(response.headers().get_one("X-Custom"), Some("1"));
724    /// assert_eq!(response.headers().len(), 1);
725    ///
726    /// response.set_raw_header("X-Custom", "2");
727    /// assert_eq!(response.headers().get_one("X-Custom"), Some("2"));
728    /// assert_eq!(response.headers().len(), 1);
729    /// ```
730    #[inline(always)]
731    pub fn set_raw_header<'a: 'r, 'b: 'r, N, V>(&mut self, name: N, value: V) -> bool
732    where
733        N: Into<Cow<'a, str>>,
734        V: Into<Cow<'b, str>>,
735    {
736        self.set_header(Header::new(name, value))
737    }
738
739    /// Adds the header `header` to `self`. If `self` contains headers with the
740    /// name `header.name`, another header with the same name and value
741    /// `header.value` is added. The type of `header` can be any type that
742    /// implements `Into<Header>`. This includes `Header` itself,
743    /// [`ContentType`](crate::http::ContentType),
744    /// [`Accept`](crate::http::Accept).
745    ///
746    /// # Example
747    ///
748    /// ```rust
749    /// # extern crate rocket_community as rocket;
750    /// use rocket::Response;
751    /// use rocket::http::{Header, Accept};
752    ///
753    /// let mut response = Response::new();
754    /// response.adjoin_header(Accept::JSON);
755    /// response.adjoin_header(Header::new("Accept", "text/plain"));
756    ///
757    /// let mut accept_headers = response.headers().iter();
758    /// assert_eq!(accept_headers.next(), Some(Header::new("Accept", "application/json")));
759    /// assert_eq!(accept_headers.next(), Some(Header::new("Accept", "text/plain")));
760    /// assert_eq!(accept_headers.next(), None);
761    /// ```
762    #[inline(always)]
763    pub fn adjoin_header<'h: 'r, H: Into<Header<'h>>>(&mut self, header: H) {
764        self.headers.add(header)
765    }
766
767    /// Adds a custom header with name `name` and value `value` to `self`. If
768    /// `self` already contains headers with the name `name`, another header
769    /// with the same `name` and `value` is added.
770    ///
771    /// # Example
772    ///
773    /// ```rust
774    /// # extern crate rocket_community as rocket;
775    /// use rocket::Response;
776    /// use rocket::http::Header;
777    ///
778    /// let mut response = Response::new();
779    /// response.adjoin_raw_header("X-Custom", "one");
780    /// response.adjoin_raw_header("X-Custom", "two");
781    ///
782    /// let mut custom_headers = response.headers().iter();
783    /// assert_eq!(custom_headers.next(), Some(Header::new("X-Custom", "one")));
784    /// assert_eq!(custom_headers.next(), Some(Header::new("X-Custom", "two")));
785    /// assert_eq!(custom_headers.next(), None);
786    /// ```
787    #[inline(always)]
788    pub fn adjoin_raw_header<'a: 'r, 'b: 'r, N, V>(&mut self, name: N, value: V)
789    where
790        N: Into<Cow<'a, str>>,
791        V: Into<Cow<'b, str>>,
792    {
793        self.adjoin_header(Header::new(name, value));
794    }
795
796    /// Removes all headers with the name `name`.
797    ///
798    /// # Example
799    ///
800    /// ```rust
801    /// # extern crate rocket_community as rocket;
802    /// use rocket::Response;
803    ///
804    /// let mut response = Response::new();
805    ///
806    /// response.adjoin_raw_header("X-Custom", "one");
807    /// response.adjoin_raw_header("X-Custom", "two");
808    /// response.adjoin_raw_header("X-Other", "hi");
809    /// assert_eq!(response.headers().len(), 3);
810    ///
811    /// response.remove_header("X-Custom");
812    /// assert_eq!(response.headers().len(), 1);
813    /// ```
814    #[inline(always)]
815    pub fn remove_header(&mut self, name: &str) {
816        self.headers.remove(name);
817    }
818
819    /// Returns an immutable borrow of the body of `self`, if there is one.
820    ///
821    /// # Example
822    ///
823    /// ```rust
824    /// # extern crate rocket_community as rocket;
825    /// use std::io::Cursor;
826    /// use rocket::Response;
827    ///
828    /// # rocket::async_test(async {
829    /// let mut response = Response::new();
830    /// assert!(response.body().is_none());
831    ///
832    /// let string = "Hello, world!";
833    /// response.set_sized_body(string.len(), Cursor::new(string));
834    /// assert!(response.body().is_some());
835    /// # })
836    /// ```
837    #[inline(always)]
838    pub fn body(&self) -> &Body<'r> {
839        &self.body
840    }
841
842    /// Returns `Ok(Some(_))` if `self` contains a suitable handler for any of
843    /// the comma-separated protocol strings in `I`. Returns `Err(_)` if
844    /// `protocols` is non-empty but no match was found in `self`. If `self`
845    /// doesn't support any kind of upgrade, return `Ok(None)`.
846    pub(crate) fn search_upgrades<'a, I: Iterator<Item = &'a str>>(
847        &mut self,
848        protocols: I,
849    ) -> Result<Option<(Uncased<'r>, Box<dyn IoHandler + 'r>)>, ()> {
850        if self.upgrade.is_empty() {
851            return Ok(None);
852        }
853
854        let mut protocols = protocols.peekable();
855        let have_protocols = protocols.peek().is_some();
856        let found = protocols
857            .flat_map(|v| v.split(',').map(str::trim))
858            .find_map(|p| self.upgrade.remove_entry(p.as_uncased()));
859
860        match found {
861            Some(handler) => Ok(Some(handler)),
862            None if have_protocols => Err(()),
863            None => Ok(None),
864        }
865    }
866
867    /// Returns the [`IoHandler`] for the protocol `proto`.
868    ///
869    /// Returns `Some` if such a handler was registered via
870    /// [`Response::add_upgrade()`] or the corresponding builder method
871    /// [`upgrade()`](Builder::upgrade()). Otherwise returns `None`.
872    ///
873    /// ```rust
874    /// # extern crate rocket_community as rocket;
875    /// use std::pin::Pin;
876    ///
877    /// use rocket::Response;
878    /// use rocket::data::{IoHandler, IoStream};
879    /// use rocket::tokio::io;
880    ///
881    /// struct EchoHandler;
882    ///
883    /// #[rocket::async_trait]
884    /// impl IoHandler for EchoHandler {
885    ///     async fn io(self: Box<Self>, io: IoStream) -> io::Result<()> {
886    ///         let (mut reader, mut writer) = io::split(io);
887    ///         io::copy(&mut reader, &mut writer).await?;
888    ///         Ok(())
889    ///     }
890    /// }
891    ///
892    /// # rocket::async_test(async {
893    /// let mut response = Response::new();
894    /// assert!(response.upgrade("raw-echo").is_none());
895    ///
896    /// response.add_upgrade("raw-echo", EchoHandler);
897    /// assert!(response.upgrade("raw-echo").is_some());
898    /// # })
899    /// ```
900    pub fn upgrade(&mut self, proto: &str) -> Option<&mut (dyn IoHandler + 'r)> {
901        self.upgrade.get_mut(proto.as_uncased()).map(|h| h.as_mut())
902    }
903
904    /// Returns a mutable borrow of the body of `self`, if there is one. A
905    /// mutable borrow allows for reading the body.
906    ///
907    /// # Example
908    ///
909    /// ```rust
910    /// # extern crate rocket_community as rocket;
911    /// use std::io::Cursor;
912    /// use rocket::Response;
913    ///
914    /// # rocket::async_test(async {
915    /// let mut response = Response::new();
916    /// assert!(response.body().is_none());
917    ///
918    /// let string = "Hello, world!";
919    /// response.set_sized_body(string.len(), Cursor::new(string));
920    /// let string = response.body_mut().to_string().await;
921    /// assert_eq!(string.unwrap(), "Hello, world!");
922    /// # })
923    /// ```
924    #[inline(always)]
925    pub fn body_mut(&mut self) -> &mut Body<'r> {
926        &mut self.body
927    }
928
929    // Makes the `AsyncRead`er in the body empty but leaves the size of the body
930    // if it exists. Meant to be used during HEAD handling.
931    #[inline(always)]
932    pub(crate) fn strip_body(&mut self) {
933        self.body.strip();
934    }
935
936    /// Sets the body of `self` to be the fixed-sized `body` with size
937    /// `size`, which may be `None`. If `size` is `None`, the body's size will
938    /// be computing with calls to `seek` just before being written out in a
939    /// response.
940    ///
941    /// # Example
942    ///
943    /// ```rust
944    /// # extern crate rocket_community as rocket;
945    /// use std::io;
946    /// use rocket::Response;
947    ///
948    /// # let o: io::Result<()> = rocket::async_test(async {
949    /// let string = "Hello, world!";
950    ///
951    /// let mut response = Response::new();
952    /// response.set_sized_body(string.len(), io::Cursor::new(string));
953    /// assert_eq!(response.body_mut().to_string().await?, "Hello, world!");
954    /// # Ok(())
955    /// # });
956    /// # assert!(o.is_ok());
957    /// ```
958    pub fn set_sized_body<B, S>(&mut self, size: S, body: B)
959    where
960        B: AsyncRead + AsyncSeek + Send + 'r,
961        S: Into<Option<usize>>,
962    {
963        self.body = Body::with_sized(body, size.into());
964    }
965
966    /// Sets the body of `self` to `body`, which will be streamed.
967    ///
968    /// The max chunk size is configured via [`Response::set_max_chunk_size()`]
969    /// and defaults to [`Body::DEFAULT_MAX_CHUNK`].
970    ///
971    /// # Example
972    ///
973    /// ```rust
974    /// # extern crate rocket_community as rocket;
975    /// # use std::io;
976    /// use tokio::io::{repeat, AsyncReadExt};
977    /// use rocket::Response;
978    ///
979    /// # let o: io::Result<()> = rocket::async_test(async {
980    /// let mut response = Response::new();
981    /// response.set_streamed_body(repeat(97).take(5));
982    /// assert_eq!(response.body_mut().to_string().await?, "aaaaa");
983    /// # Ok(())
984    /// # });
985    /// # assert!(o.is_ok());
986    /// ```
987    #[inline(always)]
988    pub fn set_streamed_body<B>(&mut self, body: B)
989    where
990        B: AsyncRead + Send + 'r,
991    {
992        self.body = Body::with_unsized(body);
993    }
994
995    /// Registers `handler` as the I/O handler for upgrade protocol `protocol`.
996    ///
997    /// Responses registering I/O handlers for upgraded protocols **should not**
998    /// set the response status to `101`, nor set the `Connection` or `Upgrade`
999    /// headers. Rocket automatically sets these headers as needed. See
1000    /// [`Response`#upgrading] for details.
1001    ///
1002    /// If a handler was previously registered for `protocol`, this `handler`
1003    /// replaces it. If the connection is upgraded to `protocol`, the last
1004    /// `handler` registered for the protocol is used to handle the connection.
1005    /// See [`IoHandler`] for details on implementing an I/O handler. For
1006    /// details on connection upgrading, see [`Response`#upgrading].
1007    ///
1008    /// [`Response`#upgrading]: Response#upgrading
1009    ///
1010    /// # Example
1011    ///
1012    /// ```rust
1013    /// # extern crate rocket_community as rocket;
1014    /// use std::pin::Pin;
1015    ///
1016    /// use rocket::Response;
1017    /// use rocket::data::{IoHandler, IoStream};
1018    /// use rocket::tokio::io;
1019    ///
1020    /// struct EchoHandler;
1021    ///
1022    /// #[rocket::async_trait]
1023    /// impl IoHandler for EchoHandler {
1024    ///     async fn io(self: Box<Self>, io: IoStream) -> io::Result<()> {
1025    ///         let (mut reader, mut writer) = io::split(io);
1026    ///         io::copy(&mut reader, &mut writer).await?;
1027    ///         Ok(())
1028    ///     }
1029    /// }
1030    ///
1031    /// # rocket::async_test(async {
1032    /// let mut response = Response::new();
1033    /// assert!(response.upgrade("raw-echo").is_none());
1034    ///
1035    /// response.add_upgrade("raw-echo", EchoHandler);
1036    /// assert!(response.upgrade("raw-echo").is_some());
1037    /// # })
1038    /// ```
1039    pub fn add_upgrade<N, H>(&mut self, protocol: N, handler: H)
1040    where
1041        N: Into<Uncased<'r>>,
1042        H: IoHandler + 'r,
1043    {
1044        self.upgrade.insert(protocol.into(), Box::new(handler));
1045    }
1046
1047    /// Sets the body's maximum chunk size to `size` bytes.
1048    ///
1049    /// The default max chunk size is [`Body::DEFAULT_MAX_CHUNK`]. The max chunk
1050    /// size is a property of the body and is thus reset whenever a body is set
1051    /// via [`Response::set_streamed_body()`], [`Response::set_sized_body()`],
1052    /// or the corresponding builder methods.
1053    ///
1054    /// This setting does not typically need to be changed. Configuring a high
1055    /// value can result in high memory usage. Similarly, configuring a low
1056    /// value can result in excessive network writes. When unsure, leave the
1057    /// value unchanged.
1058    ///
1059    /// # Example
1060    ///
1061    /// ```rust
1062    /// # extern crate rocket_community as rocket;
1063    /// use tokio::io::{repeat, AsyncReadExt};
1064    /// use rocket::Response;
1065    ///
1066    /// # let o: Option<()> = rocket::async_test(async {
1067    /// let mut response = Response::new();
1068    /// response.set_streamed_body(repeat(97).take(5));
1069    /// response.set_max_chunk_size(3072);
1070    /// # Some(())
1071    /// # });
1072    /// # assert!(o.is_some());
1073    #[inline(always)]
1074    pub fn set_max_chunk_size(&mut self, size: usize) {
1075        self.body_mut().set_max_chunk_size(size);
1076    }
1077
1078    /// Replaces this response's status and body with that of `other`, if they
1079    /// exist in `other`. Any headers that exist in `other` replace the ones in
1080    /// `self`. Any in `self` that aren't in `other` remain in `self`.
1081    ///
1082    /// # Example
1083    ///
1084    /// ```rust
1085    /// # extern crate rocket_community as rocket;
1086    /// use rocket::Response;
1087    /// use rocket::http::{Status, ContentType};
1088    ///
1089    /// let base = Response::build()
1090    ///     .status(Status::NotFound)
1091    ///     .header(ContentType::HTML)
1092    ///     .raw_header("X-Custom", "value 1")
1093    ///     .finalize();
1094    ///
1095    /// let response = Response::build()
1096    ///     .status(Status::ImATeapot)
1097    ///     .raw_header("X-Custom", "value 2")
1098    ///     .raw_header_adjoin("X-Custom", "value 3")
1099    ///     .merge(base)
1100    ///     .finalize();
1101    ///
1102    /// assert_eq!(response.status(), Status::NotFound);
1103    ///
1104    /// let ctype: Vec<_> = response.headers().get("Content-Type").collect();
1105    /// assert_eq!(ctype, vec![ContentType::HTML.to_string()]);
1106    ///
1107    /// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
1108    /// assert_eq!(custom_values, vec!["value 1"]);
1109    /// ```
1110    pub fn merge(&mut self, other: Response<'r>) {
1111        if let Some(status) = other.status {
1112            self.status = Some(status);
1113        }
1114
1115        if other.body().is_some() {
1116            self.body = other.body;
1117        }
1118
1119        for (name, values) in other.headers.into_iter_raw() {
1120            self.headers.replace_all(name.into_cow(), values);
1121        }
1122    }
1123
1124    /// Sets `self`'s status and body to that of `other` if they are not already
1125    /// set in `self`. Any headers present in both `other` and `self` are
1126    /// adjoined.
1127    ///
1128    /// # Example
1129    ///
1130    /// ```rust
1131    /// # extern crate rocket_community as rocket;
1132    /// use rocket::Response;
1133    /// use rocket::http::{Status, ContentType};
1134    ///
1135    /// let other = Response::build()
1136    ///     .status(Status::NotFound)
1137    ///     .header(ContentType::HTML)
1138    ///     .raw_header("X-Custom", "value 1")
1139    ///     .finalize();
1140    ///
1141    /// let response = Response::build()
1142    ///     .status(Status::ImATeapot)
1143    ///     .raw_header("X-Custom", "value 2")
1144    ///     .raw_header_adjoin("X-Custom", "value 3")
1145    ///     .join(other)
1146    ///     .finalize();
1147    ///
1148    /// assert_eq!(response.status(), Status::ImATeapot);
1149    ///
1150    /// let ctype: Vec<_> = response.headers().get("Content-Type").collect();
1151    /// assert_eq!(ctype, vec![ContentType::HTML.to_string()]);
1152    ///
1153    /// let custom_values: Vec<_> = response.headers().get("X-Custom").collect();
1154    /// assert_eq!(custom_values, vec!["value 2", "value 3", "value 1"]);
1155    /// ```
1156    pub fn join(&mut self, other: Response<'r>) {
1157        if self.status.is_none() {
1158            self.status = other.status;
1159        }
1160
1161        if self.body.is_none() {
1162            self.body = other.body;
1163        }
1164
1165        for (name, mut values) in other.headers.into_iter_raw() {
1166            self.headers.add_all(name.into_cow(), &mut values);
1167        }
1168    }
1169}
1170
1171impl fmt::Debug for Response<'_> {
1172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1173        writeln!(f, "{}", self.status())?;
1174
1175        for header in self.headers().iter() {
1176            writeln!(f, "{}", header)?;
1177        }
1178
1179        self.body.fmt(f)
1180    }
1181}