1 //! Http response
2 use std::cell::{Ref, RefMut};
3 use std::convert::TryFrom;
4 use std::future::Future;
5 use std::pin::Pin;
6 use std::task::{Context, Poll};
7 use std::{fmt, str};
8
9 use bytes::{Bytes, BytesMut};
10 use futures_core::Stream;
11 use serde::Serialize;
12 use serde_json;
13
14 use crate::body::{Body, BodyStream, MessageBody, ResponseBody};
15 use crate::cookie::{Cookie, CookieJar};
16 use crate::error::Error;
17 use crate::extensions::Extensions;
18 use crate::header::{Header, IntoHeaderValue};
19 use crate::http::header::{self, HeaderName, HeaderValue};
20 use crate::http::{Error as HttpError, HeaderMap, StatusCode};
21 use crate::message::{BoxedResponseHead, ConnectionType, ResponseHead};
22
23 /// An HTTP Response
24 pub struct Response<B = Body> {
25 head: BoxedResponseHead,
26 body: ResponseBody<B>,
27 error: Option<Error>,
28 }
29
30 impl Response<Body> {
31 /// Create http response builder with specific status.
32 #[inline]
build(status: StatusCode) -> ResponseBuilder33 pub fn build(status: StatusCode) -> ResponseBuilder {
34 ResponseBuilder::new(status)
35 }
36
37 /// Create http response builder
38 #[inline]
build_from<T: Into<ResponseBuilder>>(source: T) -> ResponseBuilder39 pub fn build_from<T: Into<ResponseBuilder>>(source: T) -> ResponseBuilder {
40 source.into()
41 }
42
43 /// Constructs a response
44 #[inline]
new(status: StatusCode) -> Response45 pub fn new(status: StatusCode) -> Response {
46 Response {
47 head: BoxedResponseHead::new(status),
48 body: ResponseBody::Body(Body::Empty),
49 error: None,
50 }
51 }
52
53 /// Constructs an error response
54 #[inline]
from_error(error: Error) -> Response55 pub fn from_error(error: Error) -> Response {
56 let mut resp = error.as_response_error().error_response();
57 if resp.head.status == StatusCode::INTERNAL_SERVER_ERROR {
58 error!("Internal Server Error: {:?}", error);
59 }
60 resp.error = Some(error);
61 resp
62 }
63
64 /// Convert response to response with body
into_body<B>(self) -> Response<B>65 pub fn into_body<B>(self) -> Response<B> {
66 let b = match self.body {
67 ResponseBody::Body(b) => b,
68 ResponseBody::Other(b) => b,
69 };
70 Response {
71 head: self.head,
72 error: self.error,
73 body: ResponseBody::Other(b),
74 }
75 }
76 }
77
78 impl<B> Response<B> {
79 /// Constructs a response with body
80 #[inline]
with_body(status: StatusCode, body: B) -> Response<B>81 pub fn with_body(status: StatusCode, body: B) -> Response<B> {
82 Response {
83 head: BoxedResponseHead::new(status),
84 body: ResponseBody::Body(body),
85 error: None,
86 }
87 }
88
89 #[inline]
90 /// Http message part of the response
head(&self) -> &ResponseHead91 pub fn head(&self) -> &ResponseHead {
92 &*self.head
93 }
94
95 #[inline]
96 /// Mutable reference to a http message part of the response
head_mut(&mut self) -> &mut ResponseHead97 pub fn head_mut(&mut self) -> &mut ResponseHead {
98 &mut *self.head
99 }
100
101 /// The source `error` for this response
102 #[inline]
error(&self) -> Option<&Error>103 pub fn error(&self) -> Option<&Error> {
104 self.error.as_ref()
105 }
106
107 /// Get the response status code
108 #[inline]
status(&self) -> StatusCode109 pub fn status(&self) -> StatusCode {
110 self.head.status
111 }
112
113 /// Set the `StatusCode` for this response
114 #[inline]
status_mut(&mut self) -> &mut StatusCode115 pub fn status_mut(&mut self) -> &mut StatusCode {
116 &mut self.head.status
117 }
118
119 /// Get the headers from the response
120 #[inline]
headers(&self) -> &HeaderMap121 pub fn headers(&self) -> &HeaderMap {
122 &self.head.headers
123 }
124
125 /// Get a mutable reference to the headers
126 #[inline]
headers_mut(&mut self) -> &mut HeaderMap127 pub fn headers_mut(&mut self) -> &mut HeaderMap {
128 &mut self.head.headers
129 }
130
131 /// Get an iterator for the cookies set by this response
132 #[inline]
cookies(&self) -> CookieIter<'_>133 pub fn cookies(&self) -> CookieIter<'_> {
134 CookieIter {
135 iter: self.head.headers.get_all(header::SET_COOKIE),
136 }
137 }
138
139 /// Add a cookie to this response
140 #[inline]
add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError>141 pub fn add_cookie(&mut self, cookie: &Cookie<'_>) -> Result<(), HttpError> {
142 let h = &mut self.head.headers;
143 HeaderValue::from_str(&cookie.to_string())
144 .map(|c| {
145 h.append(header::SET_COOKIE, c);
146 })
147 .map_err(|e| e.into())
148 }
149
150 /// Remove all cookies with the given name from this response. Returns
151 /// the number of cookies removed.
152 #[inline]
del_cookie(&mut self, name: &str) -> usize153 pub fn del_cookie(&mut self, name: &str) -> usize {
154 let h = &mut self.head.headers;
155 let vals: Vec<HeaderValue> = h
156 .get_all(header::SET_COOKIE)
157 .map(|v| v.to_owned())
158 .collect();
159 h.remove(header::SET_COOKIE);
160
161 let mut count: usize = 0;
162 for v in vals {
163 if let Ok(s) = v.to_str() {
164 if let Ok(c) = Cookie::parse_encoded(s) {
165 if c.name() == name {
166 count += 1;
167 continue;
168 }
169 }
170 }
171 h.append(header::SET_COOKIE, v);
172 }
173 count
174 }
175
176 /// Connection upgrade status
177 #[inline]
upgrade(&self) -> bool178 pub fn upgrade(&self) -> bool {
179 self.head.upgrade()
180 }
181
182 /// Keep-alive status for this connection
keep_alive(&self) -> bool183 pub fn keep_alive(&self) -> bool {
184 self.head.keep_alive()
185 }
186
187 /// Responses extensions
188 #[inline]
extensions(&self) -> Ref<'_, Extensions>189 pub fn extensions(&self) -> Ref<'_, Extensions> {
190 self.head.extensions.borrow()
191 }
192
193 /// Mutable reference to a the response's extensions
194 #[inline]
extensions_mut(&mut self) -> RefMut<'_, Extensions>195 pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
196 self.head.extensions.borrow_mut()
197 }
198
199 /// Get body of this response
200 #[inline]
body(&self) -> &ResponseBody<B>201 pub fn body(&self) -> &ResponseBody<B> {
202 &self.body
203 }
204
205 /// Set a body
set_body<B2>(self, body: B2) -> Response<B2>206 pub fn set_body<B2>(self, body: B2) -> Response<B2> {
207 Response {
208 head: self.head,
209 body: ResponseBody::Body(body),
210 error: None,
211 }
212 }
213
214 /// Split response and body
into_parts(self) -> (Response<()>, ResponseBody<B>)215 pub fn into_parts(self) -> (Response<()>, ResponseBody<B>) {
216 (
217 Response {
218 head: self.head,
219 body: ResponseBody::Body(()),
220 error: self.error,
221 },
222 self.body,
223 )
224 }
225
226 /// Drop request's body
drop_body(self) -> Response<()>227 pub fn drop_body(self) -> Response<()> {
228 Response {
229 head: self.head,
230 body: ResponseBody::Body(()),
231 error: None,
232 }
233 }
234
235 /// Set a body and return previous body value
replace_body<B2>(self, body: B2) -> (Response<B2>, ResponseBody<B>)236 pub(crate) fn replace_body<B2>(self, body: B2) -> (Response<B2>, ResponseBody<B>) {
237 (
238 Response {
239 head: self.head,
240 body: ResponseBody::Body(body),
241 error: self.error,
242 },
243 self.body,
244 )
245 }
246
247 /// Set a body and return previous body value
map_body<F, B2>(mut self, f: F) -> Response<B2> where F: FnOnce(&mut ResponseHead, ResponseBody<B>) -> ResponseBody<B2>,248 pub fn map_body<F, B2>(mut self, f: F) -> Response<B2>
249 where
250 F: FnOnce(&mut ResponseHead, ResponseBody<B>) -> ResponseBody<B2>,
251 {
252 let body = f(&mut self.head, self.body);
253
254 Response {
255 body,
256 head: self.head,
257 error: self.error,
258 }
259 }
260
261 /// Extract response body
take_body(&mut self) -> ResponseBody<B>262 pub fn take_body(&mut self) -> ResponseBody<B> {
263 self.body.take_body()
264 }
265 }
266
267 impl<B: MessageBody> fmt::Debug for Response<B> {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result268 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269 let res = writeln!(
270 f,
271 "\nResponse {:?} {}{}",
272 self.head.version,
273 self.head.status,
274 self.head.reason.unwrap_or(""),
275 );
276 let _ = writeln!(f, " headers:");
277 for (key, val) in self.head.headers.iter() {
278 let _ = writeln!(f, " {:?}: {:?}", key, val);
279 }
280 let _ = writeln!(f, " body: {:?}", self.body.size());
281 res
282 }
283 }
284
285 impl Future for Response {
286 type Output = Result<Response, Error>;
287
poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output>288 fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
289 Poll::Ready(Ok(Response {
290 head: self.head.take(),
291 body: self.body.take_body(),
292 error: self.error.take(),
293 }))
294 }
295 }
296
297 pub struct CookieIter<'a> {
298 iter: header::GetAll<'a>,
299 }
300
301 impl<'a> Iterator for CookieIter<'a> {
302 type Item = Cookie<'a>;
303
304 #[inline]
next(&mut self) -> Option<Cookie<'a>>305 fn next(&mut self) -> Option<Cookie<'a>> {
306 for v in self.iter.by_ref() {
307 if let Ok(c) = Cookie::parse_encoded(v.to_str().ok()?) {
308 return Some(c);
309 }
310 }
311 None
312 }
313 }
314
315 /// An HTTP response builder
316 ///
317 /// This type can be used to construct an instance of `Response` through a
318 /// builder-like pattern.
319 pub struct ResponseBuilder {
320 head: Option<BoxedResponseHead>,
321 err: Option<HttpError>,
322 cookies: Option<CookieJar>,
323 }
324
325 impl ResponseBuilder {
326 #[inline]
327 /// Create response builder
new(status: StatusCode) -> Self328 pub fn new(status: StatusCode) -> Self {
329 ResponseBuilder {
330 head: Some(BoxedResponseHead::new(status)),
331 err: None,
332 cookies: None,
333 }
334 }
335
336 /// Set HTTP status code of this response.
337 #[inline]
status(&mut self, status: StatusCode) -> &mut Self338 pub fn status(&mut self, status: StatusCode) -> &mut Self {
339 if let Some(parts) = parts(&mut self.head, &self.err) {
340 parts.status = status;
341 }
342 self
343 }
344
345 /// Set a header.
346 ///
347 /// ```rust
348 /// use actix_http::{http, Request, Response, Result};
349 ///
350 /// fn index(req: Request) -> Result<Response> {
351 /// Ok(Response::Ok()
352 /// .set(http::header::IfModifiedSince(
353 /// "Sun, 07 Nov 1994 08:48:37 GMT".parse()?,
354 /// ))
355 /// .finish())
356 /// }
357 /// ```
358 #[doc(hidden)]
set<H: Header>(&mut self, hdr: H) -> &mut Self359 pub fn set<H: Header>(&mut self, hdr: H) -> &mut Self {
360 if let Some(parts) = parts(&mut self.head, &self.err) {
361 match hdr.try_into() {
362 Ok(value) => {
363 parts.headers.append(H::name(), value);
364 }
365 Err(e) => self.err = Some(e.into()),
366 }
367 }
368 self
369 }
370
371 /// Append a header to existing headers.
372 ///
373 /// ```rust
374 /// use actix_http::{http, Request, Response};
375 ///
376 /// fn index(req: Request) -> Response {
377 /// Response::Ok()
378 /// .header("X-TEST", "value")
379 /// .header(http::header::CONTENT_TYPE, "application/json")
380 /// .finish()
381 /// }
382 /// ```
header<K, V>(&mut self, key: K, value: V) -> &mut Self where HeaderName: TryFrom<K>, <HeaderName as TryFrom<K>>::Error: Into<HttpError>, V: IntoHeaderValue,383 pub fn header<K, V>(&mut self, key: K, value: V) -> &mut Self
384 where
385 HeaderName: TryFrom<K>,
386 <HeaderName as TryFrom<K>>::Error: Into<HttpError>,
387 V: IntoHeaderValue,
388 {
389 if let Some(parts) = parts(&mut self.head, &self.err) {
390 match HeaderName::try_from(key) {
391 Ok(key) => match value.try_into() {
392 Ok(value) => {
393 parts.headers.append(key, value);
394 }
395 Err(e) => self.err = Some(e.into()),
396 },
397 Err(e) => self.err = Some(e.into()),
398 };
399 }
400 self
401 }
402
403 /// Set a header.
404 ///
405 /// ```rust
406 /// use actix_http::{http, Request, Response};
407 ///
408 /// fn index(req: Request) -> Response {
409 /// Response::Ok()
410 /// .set_header("X-TEST", "value")
411 /// .set_header(http::header::CONTENT_TYPE, "application/json")
412 /// .finish()
413 /// }
414 /// ```
set_header<K, V>(&mut self, key: K, value: V) -> &mut Self where HeaderName: TryFrom<K>, <HeaderName as TryFrom<K>>::Error: Into<HttpError>, V: IntoHeaderValue,415 pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
416 where
417 HeaderName: TryFrom<K>,
418 <HeaderName as TryFrom<K>>::Error: Into<HttpError>,
419 V: IntoHeaderValue,
420 {
421 if let Some(parts) = parts(&mut self.head, &self.err) {
422 match HeaderName::try_from(key) {
423 Ok(key) => match value.try_into() {
424 Ok(value) => {
425 parts.headers.insert(key, value);
426 }
427 Err(e) => self.err = Some(e.into()),
428 },
429 Err(e) => self.err = Some(e.into()),
430 };
431 }
432 self
433 }
434
435 /// Set the custom reason for the response.
436 #[inline]
reason(&mut self, reason: &'static str) -> &mut Self437 pub fn reason(&mut self, reason: &'static str) -> &mut Self {
438 if let Some(parts) = parts(&mut self.head, &self.err) {
439 parts.reason = Some(reason);
440 }
441 self
442 }
443
444 /// Set connection type to KeepAlive
445 #[inline]
keep_alive(&mut self) -> &mut Self446 pub fn keep_alive(&mut self) -> &mut Self {
447 if let Some(parts) = parts(&mut self.head, &self.err) {
448 parts.set_connection_type(ConnectionType::KeepAlive);
449 }
450 self
451 }
452
453 /// Set connection type to Upgrade
454 #[inline]
upgrade<V>(&mut self, value: V) -> &mut Self where V: IntoHeaderValue,455 pub fn upgrade<V>(&mut self, value: V) -> &mut Self
456 where
457 V: IntoHeaderValue,
458 {
459 if let Some(parts) = parts(&mut self.head, &self.err) {
460 parts.set_connection_type(ConnectionType::Upgrade);
461 }
462 self.set_header(header::UPGRADE, value)
463 }
464
465 /// Force close connection, even if it is marked as keep-alive
466 #[inline]
force_close(&mut self) -> &mut Self467 pub fn force_close(&mut self) -> &mut Self {
468 if let Some(parts) = parts(&mut self.head, &self.err) {
469 parts.set_connection_type(ConnectionType::Close);
470 }
471 self
472 }
473
474 /// Disable chunked transfer encoding for HTTP/1.1 streaming responses.
475 #[inline]
no_chunking(&mut self) -> &mut Self476 pub fn no_chunking(&mut self) -> &mut Self {
477 if let Some(parts) = parts(&mut self.head, &self.err) {
478 parts.no_chunking(true);
479 }
480 self
481 }
482
483 /// Set response content type
484 #[inline]
content_type<V>(&mut self, value: V) -> &mut Self where HeaderValue: TryFrom<V>, <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,485 pub fn content_type<V>(&mut self, value: V) -> &mut Self
486 where
487 HeaderValue: TryFrom<V>,
488 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
489 {
490 if let Some(parts) = parts(&mut self.head, &self.err) {
491 match HeaderValue::try_from(value) {
492 Ok(value) => {
493 parts.headers.insert(header::CONTENT_TYPE, value);
494 }
495 Err(e) => self.err = Some(e.into()),
496 };
497 }
498 self
499 }
500
501 /// Set content length
502 #[inline]
content_length(&mut self, len: u64) -> &mut Self503 pub fn content_length(&mut self, len: u64) -> &mut Self {
504 self.header(header::CONTENT_LENGTH, len)
505 }
506
507 /// Set a cookie
508 ///
509 /// ```rust
510 /// use actix_http::{http, Request, Response};
511 ///
512 /// fn index(req: Request) -> Response {
513 /// Response::Ok()
514 /// .cookie(
515 /// http::Cookie::build("name", "value")
516 /// .domain("www.rust-lang.org")
517 /// .path("/")
518 /// .secure(true)
519 /// .http_only(true)
520 /// .finish(),
521 /// )
522 /// .finish()
523 /// }
524 /// ```
cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self525 pub fn cookie<'c>(&mut self, cookie: Cookie<'c>) -> &mut Self {
526 if self.cookies.is_none() {
527 let mut jar = CookieJar::new();
528 jar.add(cookie.into_owned());
529 self.cookies = Some(jar)
530 } else {
531 self.cookies.as_mut().unwrap().add(cookie.into_owned());
532 }
533 self
534 }
535
536 /// Remove cookie
537 ///
538 /// ```rust
539 /// use actix_http::{http, Request, Response, HttpMessage};
540 ///
541 /// fn index(req: Request) -> Response {
542 /// let mut builder = Response::Ok();
543 ///
544 /// if let Some(ref cookie) = req.cookie("name") {
545 /// builder.del_cookie(cookie);
546 /// }
547 ///
548 /// builder.finish()
549 /// }
550 /// ```
del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self551 pub fn del_cookie<'a>(&mut self, cookie: &Cookie<'a>) -> &mut Self {
552 if self.cookies.is_none() {
553 self.cookies = Some(CookieJar::new())
554 }
555 let jar = self.cookies.as_mut().unwrap();
556 let cookie = cookie.clone().into_owned();
557 jar.add_original(cookie.clone());
558 jar.remove(cookie);
559 self
560 }
561
562 /// This method calls provided closure with builder reference if value is
563 /// true.
if_true<F>(&mut self, value: bool, f: F) -> &mut Self where F: FnOnce(&mut ResponseBuilder),564 pub fn if_true<F>(&mut self, value: bool, f: F) -> &mut Self
565 where
566 F: FnOnce(&mut ResponseBuilder),
567 {
568 if value {
569 f(self);
570 }
571 self
572 }
573
574 /// This method calls provided closure with builder reference if value is
575 /// Some.
if_some<T, F>(&mut self, value: Option<T>, f: F) -> &mut Self where F: FnOnce(T, &mut ResponseBuilder),576 pub fn if_some<T, F>(&mut self, value: Option<T>, f: F) -> &mut Self
577 where
578 F: FnOnce(T, &mut ResponseBuilder),
579 {
580 if let Some(val) = value {
581 f(val, self);
582 }
583 self
584 }
585
586 /// Responses extensions
587 #[inline]
extensions(&self) -> Ref<'_, Extensions>588 pub fn extensions(&self) -> Ref<'_, Extensions> {
589 let head = self.head.as_ref().expect("cannot reuse response builder");
590 head.extensions.borrow()
591 }
592
593 /// Mutable reference to a the response's extensions
594 #[inline]
extensions_mut(&mut self) -> RefMut<'_, Extensions>595 pub fn extensions_mut(&mut self) -> RefMut<'_, Extensions> {
596 let head = self.head.as_ref().expect("cannot reuse response builder");
597 head.extensions.borrow_mut()
598 }
599
600 #[inline]
601 /// Set a body and generate `Response`.
602 ///
603 /// `ResponseBuilder` can not be used after this call.
body<B: Into<Body>>(&mut self, body: B) -> Response604 pub fn body<B: Into<Body>>(&mut self, body: B) -> Response {
605 self.message_body(body.into())
606 }
607
608 /// Set a body and generate `Response`.
609 ///
610 /// `ResponseBuilder` can not be used after this call.
message_body<B>(&mut self, body: B) -> Response<B>611 pub fn message_body<B>(&mut self, body: B) -> Response<B> {
612 if let Some(e) = self.err.take() {
613 return Response::from(Error::from(e)).into_body();
614 }
615
616 let mut response = self.head.take().expect("cannot reuse response builder");
617
618 if let Some(ref jar) = self.cookies {
619 for cookie in jar.delta() {
620 match HeaderValue::from_str(&cookie.to_string()) {
621 Ok(val) => response.headers.append(header::SET_COOKIE, val),
622 Err(e) => return Response::from(Error::from(e)).into_body(),
623 };
624 }
625 }
626
627 Response {
628 head: response,
629 body: ResponseBody::Body(body),
630 error: None,
631 }
632 }
633
634 #[inline]
635 /// Set a streaming body and generate `Response`.
636 ///
637 /// `ResponseBuilder` can not be used after this call.
streaming<S, E>(&mut self, stream: S) -> Response where S: Stream<Item = Result<Bytes, E>> + 'static, E: Into<Error> + 'static,638 pub fn streaming<S, E>(&mut self, stream: S) -> Response
639 where
640 S: Stream<Item = Result<Bytes, E>> + 'static,
641 E: Into<Error> + 'static,
642 {
643 self.body(Body::from_message(BodyStream::new(stream)))
644 }
645
646 #[inline]
647 /// Set a json body and generate `Response`
648 ///
649 /// `ResponseBuilder` can not be used after this call.
json<T: Serialize>(&mut self, value: T) -> Response650 pub fn json<T: Serialize>(&mut self, value: T) -> Response {
651 self.json2(&value)
652 }
653
654 /// Set a json body and generate `Response`
655 ///
656 /// `ResponseBuilder` can not be used after this call.
json2<T: Serialize>(&mut self, value: &T) -> Response657 pub fn json2<T: Serialize>(&mut self, value: &T) -> Response {
658 match serde_json::to_string(value) {
659 Ok(body) => {
660 let contains = if let Some(parts) = parts(&mut self.head, &self.err) {
661 parts.headers.contains_key(header::CONTENT_TYPE)
662 } else {
663 true
664 };
665 if !contains {
666 self.header(header::CONTENT_TYPE, "application/json");
667 }
668
669 self.body(Body::from(body))
670 }
671 Err(e) => Error::from(e).into(),
672 }
673 }
674
675 #[inline]
676 /// Set an empty body and generate `Response`
677 ///
678 /// `ResponseBuilder` can not be used after this call.
finish(&mut self) -> Response679 pub fn finish(&mut self) -> Response {
680 self.body(Body::Empty)
681 }
682
683 /// This method construct new `ResponseBuilder`
take(&mut self) -> ResponseBuilder684 pub fn take(&mut self) -> ResponseBuilder {
685 ResponseBuilder {
686 head: self.head.take(),
687 err: self.err.take(),
688 cookies: self.cookies.take(),
689 }
690 }
691 }
692
693 #[inline]
parts<'a>( parts: &'a mut Option<BoxedResponseHead>, err: &Option<HttpError>, ) -> Option<&'a mut ResponseHead>694 fn parts<'a>(
695 parts: &'a mut Option<BoxedResponseHead>,
696 err: &Option<HttpError>,
697 ) -> Option<&'a mut ResponseHead> {
698 if err.is_some() {
699 return None;
700 }
701 parts.as_mut().map(|r| &mut **r)
702 }
703
704 /// Convert `Response` to a `ResponseBuilder`. Body get dropped.
705 impl<B> From<Response<B>> for ResponseBuilder {
from(res: Response<B>) -> ResponseBuilder706 fn from(res: Response<B>) -> ResponseBuilder {
707 // If this response has cookies, load them into a jar
708 let mut jar: Option<CookieJar> = None;
709 for c in res.cookies() {
710 if let Some(ref mut j) = jar {
711 j.add_original(c.into_owned());
712 } else {
713 let mut j = CookieJar::new();
714 j.add_original(c.into_owned());
715 jar = Some(j);
716 }
717 }
718
719 ResponseBuilder {
720 head: Some(res.head),
721 err: None,
722 cookies: jar,
723 }
724 }
725 }
726
727 /// Convert `ResponseHead` to a `ResponseBuilder`
728 impl<'a> From<&'a ResponseHead> for ResponseBuilder {
from(head: &'a ResponseHead) -> ResponseBuilder729 fn from(head: &'a ResponseHead) -> ResponseBuilder {
730 // If this response has cookies, load them into a jar
731 let mut jar: Option<CookieJar> = None;
732
733 let cookies = CookieIter {
734 iter: head.headers.get_all(header::SET_COOKIE),
735 };
736 for c in cookies {
737 if let Some(ref mut j) = jar {
738 j.add_original(c.into_owned());
739 } else {
740 let mut j = CookieJar::new();
741 j.add_original(c.into_owned());
742 jar = Some(j);
743 }
744 }
745
746 let mut msg = BoxedResponseHead::new(head.status);
747 msg.version = head.version;
748 msg.reason = head.reason;
749 for (k, v) in &head.headers {
750 msg.headers.append(k.clone(), v.clone());
751 }
752 msg.no_chunking(!head.chunked());
753
754 ResponseBuilder {
755 head: Some(msg),
756 err: None,
757 cookies: jar,
758 }
759 }
760 }
761
762 impl Future for ResponseBuilder {
763 type Output = Result<Response, Error>;
764
poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output>765 fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
766 Poll::Ready(Ok(self.finish()))
767 }
768 }
769
770 impl fmt::Debug for ResponseBuilder {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result771 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
772 let head = self.head.as_ref().unwrap();
773
774 let res = writeln!(
775 f,
776 "\nResponseBuilder {:?} {}{}",
777 head.version,
778 head.status,
779 head.reason.unwrap_or(""),
780 );
781 let _ = writeln!(f, " headers:");
782 for (key, val) in head.headers.iter() {
783 let _ = writeln!(f, " {:?}: {:?}", key, val);
784 }
785 res
786 }
787 }
788
789 /// Helper converters
790 impl<I: Into<Response>, E: Into<Error>> From<Result<I, E>> for Response {
from(res: Result<I, E>) -> Self791 fn from(res: Result<I, E>) -> Self {
792 match res {
793 Ok(val) => val.into(),
794 Err(err) => err.into().into(),
795 }
796 }
797 }
798
799 impl From<ResponseBuilder> for Response {
from(mut builder: ResponseBuilder) -> Self800 fn from(mut builder: ResponseBuilder) -> Self {
801 builder.finish()
802 }
803 }
804
805 impl From<&'static str> for Response {
from(val: &'static str) -> Self806 fn from(val: &'static str) -> Self {
807 Response::Ok()
808 .content_type("text/plain; charset=utf-8")
809 .body(val)
810 }
811 }
812
813 impl From<&'static [u8]> for Response {
from(val: &'static [u8]) -> Self814 fn from(val: &'static [u8]) -> Self {
815 Response::Ok()
816 .content_type("application/octet-stream")
817 .body(val)
818 }
819 }
820
821 impl From<String> for Response {
from(val: String) -> Self822 fn from(val: String) -> Self {
823 Response::Ok()
824 .content_type("text/plain; charset=utf-8")
825 .body(val)
826 }
827 }
828
829 impl<'a> From<&'a String> for Response {
from(val: &'a String) -> Self830 fn from(val: &'a String) -> Self {
831 Response::Ok()
832 .content_type("text/plain; charset=utf-8")
833 .body(val)
834 }
835 }
836
837 impl From<Bytes> for Response {
from(val: Bytes) -> Self838 fn from(val: Bytes) -> Self {
839 Response::Ok()
840 .content_type("application/octet-stream")
841 .body(val)
842 }
843 }
844
845 impl From<BytesMut> for Response {
from(val: BytesMut) -> Self846 fn from(val: BytesMut) -> Self {
847 Response::Ok()
848 .content_type("application/octet-stream")
849 .body(val)
850 }
851 }
852
853 #[cfg(test)]
854 mod tests {
855 use super::*;
856 use crate::body::Body;
857 use crate::http::header::{HeaderValue, CONTENT_TYPE, COOKIE, SET_COOKIE};
858
859 #[test]
test_debug()860 fn test_debug() {
861 let resp = Response::Ok()
862 .header(COOKIE, HeaderValue::from_static("cookie1=value1; "))
863 .header(COOKIE, HeaderValue::from_static("cookie2=value2; "))
864 .finish();
865 let dbg = format!("{:?}", resp);
866 assert!(dbg.contains("Response"));
867 }
868
869 #[test]
test_response_cookies()870 fn test_response_cookies() {
871 use crate::httpmessage::HttpMessage;
872
873 let req = crate::test::TestRequest::default()
874 .header(COOKIE, "cookie1=value1")
875 .header(COOKIE, "cookie2=value2")
876 .finish();
877 let cookies = req.cookies().unwrap();
878
879 let resp = Response::Ok()
880 .cookie(
881 crate::http::Cookie::build("name", "value")
882 .domain("www.rust-lang.org")
883 .path("/test")
884 .http_only(true)
885 .max_age_time(time::Duration::days(1))
886 .finish(),
887 )
888 .del_cookie(&cookies[1])
889 .finish();
890
891 let mut val: Vec<_> = resp
892 .headers()
893 .get_all(SET_COOKIE)
894 .map(|v| v.to_str().unwrap().to_owned())
895 .collect();
896 val.sort();
897 assert!(val[0].starts_with("cookie1=; Max-Age=0;"));
898 assert_eq!(
899 val[1],
900 "name=value; HttpOnly; Path=/test; Domain=www.rust-lang.org; Max-Age=86400"
901 );
902 }
903
904 #[test]
test_update_response_cookies()905 fn test_update_response_cookies() {
906 let mut r = Response::Ok()
907 .cookie(crate::http::Cookie::new("original", "val100"))
908 .finish();
909
910 r.add_cookie(&crate::http::Cookie::new("cookie2", "val200"))
911 .unwrap();
912 r.add_cookie(&crate::http::Cookie::new("cookie2", "val250"))
913 .unwrap();
914 r.add_cookie(&crate::http::Cookie::new("cookie3", "val300"))
915 .unwrap();
916
917 assert_eq!(r.cookies().count(), 4);
918 r.del_cookie("cookie2");
919
920 let mut iter = r.cookies();
921 let v = iter.next().unwrap();
922 assert_eq!((v.name(), v.value()), ("cookie3", "val300"));
923 let v = iter.next().unwrap();
924 assert_eq!((v.name(), v.value()), ("original", "val100"));
925 }
926
927 #[test]
test_basic_builder()928 fn test_basic_builder() {
929 let resp = Response::Ok().header("X-TEST", "value").finish();
930 assert_eq!(resp.status(), StatusCode::OK);
931 }
932
933 #[test]
test_upgrade()934 fn test_upgrade() {
935 let resp = Response::build(StatusCode::OK)
936 .upgrade("websocket")
937 .finish();
938 assert!(resp.upgrade());
939 assert_eq!(
940 resp.headers().get(header::UPGRADE).unwrap(),
941 HeaderValue::from_static("websocket")
942 );
943 }
944
945 #[test]
test_force_close()946 fn test_force_close() {
947 let resp = Response::build(StatusCode::OK).force_close().finish();
948 assert!(!resp.keep_alive())
949 }
950
951 #[test]
test_content_type()952 fn test_content_type() {
953 let resp = Response::build(StatusCode::OK)
954 .content_type("text/plain")
955 .body(Body::Empty);
956 assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "text/plain")
957 }
958
959 #[test]
test_json()960 fn test_json() {
961 let resp = Response::build(StatusCode::OK).json(vec!["v1", "v2", "v3"]);
962 let ct = resp.headers().get(CONTENT_TYPE).unwrap();
963 assert_eq!(ct, HeaderValue::from_static("application/json"));
964 assert_eq!(resp.body().get_ref(), b"[\"v1\",\"v2\",\"v3\"]");
965 }
966
967 #[test]
test_json_ct()968 fn test_json_ct() {
969 let resp = Response::build(StatusCode::OK)
970 .header(CONTENT_TYPE, "text/json")
971 .json(vec!["v1", "v2", "v3"]);
972 let ct = resp.headers().get(CONTENT_TYPE).unwrap();
973 assert_eq!(ct, HeaderValue::from_static("text/json"));
974 assert_eq!(resp.body().get_ref(), b"[\"v1\",\"v2\",\"v3\"]");
975 }
976
977 #[test]
test_json2()978 fn test_json2() {
979 let resp = Response::build(StatusCode::OK).json2(&vec!["v1", "v2", "v3"]);
980 let ct = resp.headers().get(CONTENT_TYPE).unwrap();
981 assert_eq!(ct, HeaderValue::from_static("application/json"));
982 assert_eq!(resp.body().get_ref(), b"[\"v1\",\"v2\",\"v3\"]");
983 }
984
985 #[test]
test_json2_ct()986 fn test_json2_ct() {
987 let resp = Response::build(StatusCode::OK)
988 .header(CONTENT_TYPE, "text/json")
989 .json2(&vec!["v1", "v2", "v3"]);
990 let ct = resp.headers().get(CONTENT_TYPE).unwrap();
991 assert_eq!(ct, HeaderValue::from_static("text/json"));
992 assert_eq!(resp.body().get_ref(), b"[\"v1\",\"v2\",\"v3\"]");
993 }
994
995 #[test]
test_serde_json_in_body()996 fn test_serde_json_in_body() {
997 use serde_json::json;
998 let resp =
999 Response::build(StatusCode::OK).body(json!({"test-key":"test-value"}));
1000 assert_eq!(resp.body().get_ref(), br#"{"test-key":"test-value"}"#);
1001 }
1002
1003 #[test]
test_into_response()1004 fn test_into_response() {
1005 let resp: Response = "test".into();
1006 assert_eq!(resp.status(), StatusCode::OK);
1007 assert_eq!(
1008 resp.headers().get(CONTENT_TYPE).unwrap(),
1009 HeaderValue::from_static("text/plain; charset=utf-8")
1010 );
1011 assert_eq!(resp.status(), StatusCode::OK);
1012 assert_eq!(resp.body().get_ref(), b"test");
1013
1014 let resp: Response = b"test".as_ref().into();
1015 assert_eq!(resp.status(), StatusCode::OK);
1016 assert_eq!(
1017 resp.headers().get(CONTENT_TYPE).unwrap(),
1018 HeaderValue::from_static("application/octet-stream")
1019 );
1020 assert_eq!(resp.status(), StatusCode::OK);
1021 assert_eq!(resp.body().get_ref(), b"test");
1022
1023 let resp: Response = "test".to_owned().into();
1024 assert_eq!(resp.status(), StatusCode::OK);
1025 assert_eq!(
1026 resp.headers().get(CONTENT_TYPE).unwrap(),
1027 HeaderValue::from_static("text/plain; charset=utf-8")
1028 );
1029 assert_eq!(resp.status(), StatusCode::OK);
1030 assert_eq!(resp.body().get_ref(), b"test");
1031
1032 let resp: Response = (&"test".to_owned()).into();
1033 assert_eq!(resp.status(), StatusCode::OK);
1034 assert_eq!(
1035 resp.headers().get(CONTENT_TYPE).unwrap(),
1036 HeaderValue::from_static("text/plain; charset=utf-8")
1037 );
1038 assert_eq!(resp.status(), StatusCode::OK);
1039 assert_eq!(resp.body().get_ref(), b"test");
1040
1041 let b = Bytes::from_static(b"test");
1042 let resp: Response = b.into();
1043 assert_eq!(resp.status(), StatusCode::OK);
1044 assert_eq!(
1045 resp.headers().get(CONTENT_TYPE).unwrap(),
1046 HeaderValue::from_static("application/octet-stream")
1047 );
1048 assert_eq!(resp.status(), StatusCode::OK);
1049 assert_eq!(resp.body().get_ref(), b"test");
1050
1051 let b = Bytes::from_static(b"test");
1052 let resp: Response = b.into();
1053 assert_eq!(resp.status(), StatusCode::OK);
1054 assert_eq!(
1055 resp.headers().get(CONTENT_TYPE).unwrap(),
1056 HeaderValue::from_static("application/octet-stream")
1057 );
1058 assert_eq!(resp.status(), StatusCode::OK);
1059 assert_eq!(resp.body().get_ref(), b"test");
1060
1061 let b = BytesMut::from("test");
1062 let resp: Response = b.into();
1063 assert_eq!(resp.status(), StatusCode::OK);
1064 assert_eq!(
1065 resp.headers().get(CONTENT_TYPE).unwrap(),
1066 HeaderValue::from_static("application/octet-stream")
1067 );
1068
1069 assert_eq!(resp.status(), StatusCode::OK);
1070 assert_eq!(resp.body().get_ref(), b"test");
1071 }
1072
1073 #[test]
test_into_builder()1074 fn test_into_builder() {
1075 let mut resp: Response = "test".into();
1076 assert_eq!(resp.status(), StatusCode::OK);
1077
1078 resp.add_cookie(&crate::http::Cookie::new("cookie1", "val100"))
1079 .unwrap();
1080
1081 let mut builder: ResponseBuilder = resp.into();
1082 let resp = builder.status(StatusCode::BAD_REQUEST).finish();
1083 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
1084
1085 let cookie = resp.cookies().next().unwrap();
1086 assert_eq!((cookie.name(), cookie.value()), ("cookie1", "val100"));
1087 }
1088 }
1089