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}