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}