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