rocket/response/
response.rs

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