1use std::{cell::Ref, cell::RefMut, error::Error, fmt, fmt::Write, str};
3
4use serde::Serialize;
5
6#[cfg(feature = "cookie")]
7use coo_kie::{Cookie, CookieJar};
8
9use crate::http::StatusCode;
10use crate::http::body::{Body, BodyStream, MessageBody, ResponseBody};
11use crate::http::error::{HttpError, ResponseError};
12use crate::http::header::{self, HeaderMap, HeaderName, HeaderValue};
13use crate::http::message::{ConnectionType, Message, ResponseHead};
14use crate::util::{Bytes, BytesMut, Extensions, Stream};
15
16pub struct Response<B = Body> {
18 body: ResponseBody<B>,
19 head: Message<ResponseHead>,
20}
21
22impl Response<Body> {
23 #[inline]
25 pub fn builder(status: StatusCode) -> ResponseBuilder {
26 ResponseBuilder::new(status)
27 }
28
29 #[inline]
31 pub fn builder_from<T: Into<ResponseBuilder>>(source: T) -> ResponseBuilder {
32 source.into()
33 }
34
35 #[inline]
37 pub fn new(status: StatusCode) -> Response {
38 Response {
39 head: Message::with_status(status),
40 body: ResponseBody::Body(Body::Empty),
41 }
42 }
43
44 #[inline]
46 pub fn render_with<B: fmt::Display>(status: StatusCode, body: &B) -> Response {
47 let mut resp = Response::new(status);
48 let mut buf = BytesMut::new();
49 let _ = write!(&mut buf, "{body}");
50 resp.headers_mut().insert(
51 header::CONTENT_TYPE,
52 header::HeaderValue::from_static("text/plain; charset=utf-8"),
53 );
54 resp.set_body(Body::from(buf))
55 }
56
57 pub fn into_body<B>(self) -> Response<B> {
59 let b = match self.body {
60 ResponseBody::Body(b) | ResponseBody::Other(b) => b,
61 };
62 Response {
63 head: self.head,
64 body: ResponseBody::Other(b),
65 }
66 }
67}
68
69impl<B> Response<B> {
70 #[inline]
72 pub fn with_body(status: StatusCode, body: B) -> Response<B> {
73 Response {
74 head: Message::with_status(status),
75 body: ResponseBody::Body(body),
76 }
77 }
78
79 #[inline]
80 pub fn head(&self) -> &ResponseHead {
82 &self.head
83 }
84
85 #[inline]
86 pub fn head_mut(&mut self) -> &mut ResponseHead {
88 &mut self.head
89 }
90
91 #[inline]
93 pub fn status(&self) -> StatusCode {
94 self.head.status
95 }
96
97 #[inline]
99 pub fn status_mut(&mut self) -> &mut StatusCode {
100 &mut self.head.status
101 }
102
103 #[inline]
105 pub fn headers(&self) -> &HeaderMap {
106 &self.head.headers
107 }
108
109 #[inline]
111 pub fn headers_mut(&mut self) -> &mut HeaderMap {
112 &mut self.head.headers
113 }
114
115 #[cfg(feature = "cookie")]
116 #[inline]
118 pub fn cookies(&self) -> CookieIter<'_> {
119 CookieIter {
120 iter: self.head.headers.get_all(header::SET_COOKIE),
121 }
122 }
123
124 #[cfg(feature = "cookie")]
125 #[inline]
127 pub fn add_cookie<'a, C>(&mut self, cookie: C) -> Result<(), HttpError>
128 where
129 C: Into<Cookie<'a>>,
130 {
131 let h = &mut self.head.headers;
132 let c = cookie.into();
133 HeaderValue::try_from(c.to_string())
134 .map(|c| {
135 h.append(header::SET_COOKIE, c);
136 })
137 .map_err(Into::into)
138 }
139
140 #[cfg(feature = "cookie")]
141 #[inline]
145 pub fn del_cookie(&mut self, name: &str) -> usize {
146 let h = &mut self.head.headers;
147 let vals: Vec<HeaderValue> = h
148 .get_all(header::SET_COOKIE)
149 .map(ToOwned::to_owned)
150 .collect();
151 h.remove(header::SET_COOKIE);
152
153 let mut count: usize = 0;
154 for v in vals {
155 if let Ok(s) = v.to_str()
156 && let Ok(c) = Cookie::parse_encoded(s)
157 && c.name() == name
158 {
159 count += 1;
160 continue;
161 }
162 h.append(header::SET_COOKIE, v);
163 }
164 count
165 }
166
167 #[inline]
169 pub fn upgrade(&self) -> bool {
170 self.head.upgrade()
171 }
172
173 pub fn keep_alive(&self) -> bool {
175 self.head.keep_alive()
176 }
177
178 #[inline]
180 pub fn extensions(&self) -> Ref<'_, Extensions> {
181 self.head.extensions.borrow()
182 }
183
184 #[inline]
186 pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
187 self.head.extensions.borrow_mut()
188 }
189
190 #[inline]
192 pub fn body(&self) -> &ResponseBody<B> {
193 &self.body
194 }
195
196 pub fn set_body<B2>(self, body: B2) -> Response<B2> {
198 Response {
199 head: self.head,
200 body: ResponseBody::Body(body),
201 }
202 }
203
204 pub fn into_parts(self) -> (Response<()>, ResponseBody<B>) {
206 (
207 Response {
208 head: self.head,
209 body: ResponseBody::Body(()),
210 },
211 self.body,
212 )
213 }
214
215 pub fn drop_body(self) -> Response<()> {
217 Response {
218 head: self.head,
219 body: ResponseBody::Body(()),
220 }
221 }
222
223 pub fn map_body<F, B2>(mut self, f: F) -> Response<B2>
225 where
226 F: FnOnce(&mut ResponseHead, ResponseBody<B>) -> ResponseBody<B2>,
227 {
228 let body = f(&mut self.head, self.body);
229
230 Response {
231 body,
232 head: self.head,
233 }
234 }
235
236 pub fn take_body(&mut self) -> ResponseBody<B> {
238 self.body.take_body()
239 }
240}
241
242#[cfg(test)]
243impl Response<Body> {
244 pub(crate) fn get_body_ref(&self) -> &[u8] {
245 let b = match *self.body() {
246 ResponseBody::Body(ref b) | ResponseBody::Other(ref b) => b,
247 };
248 if let Body::Bytes(bin) = b { bin } else { panic!() }
249 }
250}
251
252impl Response<Body> {
253 #[must_use]
254 pub fn take(&mut self) -> Response {
260 Response {
261 head: self.head.copy(),
262 body: self.body.take_body(),
263 }
264 }
265}
266
267impl<B: MessageBody> fmt::Display for Response<B> {
268 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
269 writeln!(
270 f,
271 "Response<{:?} {}{}>",
272 self.head.version,
273 self.head.status,
274 self.head.reason.unwrap_or(""),
275 )
276 }
277}
278
279impl<B: MessageBody> fmt::Debug for Response<B> {
280 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
281 let res = writeln!(
282 f,
283 "\nResponse {:?} {}{}",
284 self.head.version,
285 self.head.status,
286 self.head.reason.unwrap_or(""),
287 );
288 let _ = writeln!(f, " headers:");
289 for (key, val) in &self.head.headers {
290 let _ = writeln!(f, " {key:?}: {val:?}");
291 }
292 let _ = writeln!(f, " body: {:?}", self.body.size());
293 res
294 }
295}
296
297#[cfg(feature = "cookie")]
298#[derive(Debug)]
299pub struct CookieIter<'a> {
303 iter: header::GetAll<'a>,
304}
305
306#[cfg(feature = "cookie")]
307impl<'a> Iterator for CookieIter<'a> {
308 type Item = Cookie<'a>;
309
310 #[inline]
311 fn next(&mut self) -> Option<Cookie<'a>> {
312 for v in self.iter.by_ref() {
313 if let Ok(c) = Cookie::parse_encoded(v.to_str().ok()?) {
314 return Some(c);
315 }
316 }
317 None
318 }
319}
320
321pub struct ResponseBuilder {
333 head: Option<Message<ResponseHead>>,
334 err: Option<HttpError>,
335 #[cfg(feature = "cookie")]
336 cookies: Option<CookieJar>,
337}
338
339impl ResponseBuilder {
340 #[inline]
341 #[must_use]
342 pub fn new(status: StatusCode) -> Self {
344 ResponseBuilder {
345 head: Some(Message::with_status(status)),
346 err: None,
347 #[cfg(feature = "cookie")]
348 cookies: None,
349 }
350 }
351
352 #[inline]
354 pub fn status(&mut self, status: StatusCode) -> &mut Self {
355 if let Some(parts) = parts(&mut self.head, self.err) {
356 parts.status = status;
357 }
358 self
359 }
360
361 pub fn header<K, V>(&mut self, key: K, value: V) -> &mut Self
374 where
375 HeaderName: TryFrom<K>,
376 HeaderValue: TryFrom<V>,
377 <HeaderName as TryFrom<K>>::Error: Into<HttpError>,
378 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
379 {
380 if let Some(parts) = parts(&mut self.head, self.err) {
381 match HeaderName::try_from(key) {
382 Ok(key) => match HeaderValue::try_from(value) {
383 Ok(value) => {
384 parts.headers.append(key, value);
385 }
386 Err(e) => self.err = Some(log_error(e)),
387 },
388 Err(e) => self.err = Some(log_error(e)),
389 }
390 }
391 self
392 }
393
394 pub fn set_header<K, V>(&mut self, key: K, value: V) -> &mut Self
407 where
408 HeaderName: TryFrom<K>,
409 HeaderValue: TryFrom<V>,
410 <HeaderName as TryFrom<K>>::Error: Into<HttpError>,
411 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
412 {
413 if let Some(parts) = parts(&mut self.head, self.err) {
414 match HeaderName::try_from(key) {
415 Ok(key) => match HeaderValue::try_from(value) {
416 Ok(value) => {
417 parts.headers.insert(key, value);
418 }
419 Err(e) => self.err = Some(log_error(e)),
420 },
421 Err(e) => self.err = Some(log_error(e)),
422 }
423 }
424 self
425 }
426
427 #[inline]
429 pub fn reason(&mut self, reason: &'static str) -> &mut Self {
430 if let Some(parts) = parts(&mut self.head, self.err) {
431 parts.reason = Some(reason);
432 }
433 self
434 }
435
436 #[inline]
441 pub fn keep_alive(&mut self) -> &mut Self {
442 if let Some(parts) = parts(&mut self.head, self.err) {
443 parts.set_connection_type(ConnectionType::KeepAlive);
444 }
445 self
446 }
447
448 #[inline]
450 pub fn upgrade<V>(&mut self, value: V) -> &mut Self
451 where
452 HeaderValue: TryFrom<V>,
453 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
454 {
455 if let Some(parts) = parts(&mut self.head, self.err) {
456 parts.set_connection_type(ConnectionType::Upgrade);
457 }
458 self.set_header(header::UPGRADE, value)
459 }
460
461 #[inline]
463 pub fn force_close(&mut self) -> &mut Self {
464 if let Some(parts) = parts(&mut self.head, self.err) {
465 parts.set_connection_type(ConnectionType::Close);
466 }
467 self
468 }
469
470 #[inline]
472 pub fn no_chunking(&mut self) -> &mut Self {
473 if let Some(parts) = parts(&mut self.head, self.err) {
474 parts.no_chunking(true);
475 }
476 self
477 }
478
479 #[inline]
481 pub fn content_type<V>(&mut self, value: V) -> &mut Self
482 where
483 HeaderValue: TryFrom<V>,
484 <HeaderValue as TryFrom<V>>::Error: Into<HttpError>,
485 {
486 if let Some(parts) = parts(&mut self.head, self.err) {
487 match HeaderValue::try_from(value) {
488 Ok(value) => {
489 parts.headers.insert(header::CONTENT_TYPE, value);
490 }
491 Err(e) => self.err = Some(log_error(e)),
492 }
493 }
494 self
495 }
496
497 #[inline]
499 pub fn content_length(&mut self, len: u64) -> &mut Self {
500 self.header(header::CONTENT_LENGTH, len)
501 }
502
503 #[cfg(feature = "cookie")]
504 pub fn cookie<C>(&mut self, cookie: C) -> &mut Self
523 where
524 C: Into<Cookie<'static>>,
525 {
526 if let Some(cookies) = &mut self.cookies {
527 cookies.add(cookie.into());
528 } else {
529 let mut jar = CookieJar::new();
530 jar.add(cookie.into());
531 self.cookies = Some(jar);
532 }
533 self
534 }
535
536 #[cfg(feature = "cookie")]
537 pub fn del_cookie(&mut self, cookie: &Cookie<'_>) -> &mut Self {
553 if self.cookies.is_none() {
554 self.cookies = Some(CookieJar::new());
555 }
556 let jar = self.cookies.as_mut().unwrap();
557 let cookie = cookie.clone().into_owned();
558 jar.add_original(cookie.clone());
559 jar.remove(cookie);
560 self
561 }
562
563 #[inline]
569 pub fn extensions(&self) -> Ref<'_, Extensions> {
570 let head = self.head.as_ref().expect("cannot reuse response builder");
571 head.extensions.borrow()
572 }
573
574 #[inline]
580 pub fn extensions_mut(&self) -> RefMut<'_, Extensions> {
581 let head = self.head.as_ref().expect("cannot reuse response builder");
582 head.extensions.borrow_mut()
583 }
584
585 #[inline]
586 pub fn body<B: Into<Body>>(&mut self, body: B) -> Response {
592 self.message_body(body.into())
593 }
594
595 pub fn message_body<B>(&mut self, body: B) -> Response<B> {
601 if let Some(e) = self.err.take() {
602 return Response::from(e).into_body();
603 }
604
605 #[allow(unused_mut)]
606 let mut response = self.head.take().expect("cannot reuse response builder");
607
608 #[cfg(feature = "cookie")]
609 {
610 if let Some(ref jar) = self.cookies {
611 for cookie in jar.delta() {
612 match HeaderValue::from_str(&cookie.to_string()) {
613 Ok(val) => response.headers.append(header::SET_COOKIE, val),
614 Err(e) => return Response::from(HttpError::from(e)).into_body(),
615 }
616 }
617 }
618 }
619
620 Response {
621 head: response,
622 body: ResponseBody::Body(body),
623 }
624 }
625
626 #[inline]
627 #[must_use]
628 pub fn streaming<S, E>(&mut self, stream: S) -> Response
634 where
635 S: Stream<Item = Result<Bytes, E>> + Unpin + 'static,
636 E: Error + 'static,
637 {
638 self.body(Body::from_message(BodyStream::new(stream)))
639 }
640
641 #[must_use]
642 pub fn json<T: Serialize>(&mut self, value: &T) -> Response {
653 match super::helpers::json_body(value) {
654 Ok(body) => {
655 let contains = if let Some(parts) = parts(&mut self.head, self.err) {
656 parts.headers.contains_key(header::CONTENT_TYPE)
657 } else {
658 true
659 };
660 if !contains {
661 self.header(header::CONTENT_TYPE, "application/json");
662 }
663
664 self.body(Body::from(body))
665 }
666 Err(e) => e.into(),
667 }
668 }
669
670 #[inline]
671 #[must_use]
672 pub fn build(&mut self) -> Response {
678 self.body(Body::Empty)
679 }
680
681 #[must_use]
682 pub fn take(&mut self) -> ResponseBuilder {
686 ResponseBuilder {
687 head: self.head.take(),
688 err: self.err.take(),
689 #[cfg(feature = "cookie")]
690 cookies: self.cookies.take(),
691 }
692 }
693}
694
695#[inline]
696#[allow(clippy::ref_option)]
697fn parts(
698 parts: &mut Option<Message<ResponseHead>>,
699 err: Option<HttpError>,
700) -> Option<&mut ResponseHead> {
701 if err.is_some() {
702 return None;
703 }
704 parts.as_mut().map(|r| &mut **r)
705}
706
707impl<B> From<Response<B>> for ResponseBuilder {
709 fn from(res: Response<B>) -> ResponseBuilder {
710 #[cfg(feature = "cookie")]
711 {
712 let mut jar: Option<CookieJar> = None;
714 for c in res.cookies() {
715 if let Some(ref mut j) = jar {
716 j.add_original(c.into_owned());
717 } else {
718 let mut j = CookieJar::new();
719 j.add_original(c.into_owned());
720 jar = Some(j);
721 }
722 }
723
724 ResponseBuilder {
725 head: Some(res.head),
726 err: None,
727 cookies: jar,
728 }
729 }
730 #[cfg(not(feature = "cookie"))]
731 {
732 ResponseBuilder {
733 head: Some(res.head),
734 err: None,
735 }
736 }
737 }
738}
739
740impl<'a> From<&'a ResponseHead> for ResponseBuilder {
742 fn from(head: &'a ResponseHead) -> ResponseBuilder {
743 let mut msg = Message::with_status(head.status);
744 msg.version = head.version;
745 msg.reason = head.reason;
746 for (k, v) in &head.headers {
747 msg.headers.append(k.clone(), v.clone());
748 }
749 msg.no_chunking(!head.chunked());
750
751 #[cfg(feature = "cookie")]
752 {
753 let mut jar: Option<CookieJar> = None;
755
756 let cookies = CookieIter {
757 iter: head.headers.get_all(header::SET_COOKIE),
758 };
759 for c in cookies {
760 if let Some(ref mut j) = jar {
761 j.add_original(c.into_owned());
762 } else {
763 let mut j = CookieJar::new();
764 j.add_original(c.into_owned());
765 jar = Some(j);
766 }
767 }
768 ResponseBuilder {
769 head: Some(msg),
770 err: None,
771 cookies: jar,
772 }
773 }
774
775 #[cfg(not(feature = "cookie"))]
776 {
777 ResponseBuilder {
778 head: Some(msg),
779 err: None,
780 }
781 }
782 }
783}
784
785impl fmt::Debug for ResponseBuilder {
786 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
787 let head = self.head.as_ref().unwrap();
788
789 let res = writeln!(
790 f,
791 "\nResponseBuilder {:?} {}{}",
792 head.version,
793 head.status,
794 head.reason.unwrap_or(""),
795 );
796 let _ = writeln!(f, " headers:");
797 for (key, val) in &head.headers {
798 let _ = writeln!(f, " {key:?}: {val:?}");
799 }
800 res
801 }
802}
803
804fn log_error<T: Into<HttpError>>(err: T) -> HttpError {
805 let e = err.into();
806 log::error!("Error in ResponseBuilder {e}");
807 e
808}
809
810impl<I: Into<Response>, E> From<Result<I, E>> for Response
812where
813 E: ResponseError + fmt::Debug,
814{
815 fn from(res: Result<I, E>) -> Self {
816 match res {
817 Ok(val) => val.into(),
818 Err(err) => err.into(),
819 }
820 }
821}
822
823impl From<ResponseBuilder> for Response {
824 fn from(mut builder: ResponseBuilder) -> Self {
825 builder.build()
826 }
827}
828
829impl From<&'static str> for Response {
830 fn from(val: &'static str) -> Self {
831 Response::Ok()
832 .content_type("text/plain; charset=utf-8")
833 .body(val)
834 }
835}
836
837impl From<&'static [u8]> for Response {
838 fn from(val: &'static [u8]) -> Self {
839 Response::Ok()
840 .content_type("application/octet-stream")
841 .body(val)
842 }
843}
844
845impl From<String> for Response {
846 fn from(val: String) -> Self {
847 Response::Ok()
848 .content_type("text/plain; charset=utf-8")
849 .body(val)
850 }
851}
852
853impl<'a> From<&'a String> for Response {
854 fn from(val: &'a String) -> Self {
855 Response::Ok()
856 .content_type("text/plain; charset=utf-8")
857 .body(val)
858 }
859}
860
861impl From<Bytes> for Response {
862 fn from(val: Bytes) -> Self {
863 Response::Ok()
864 .content_type("application/octet-stream")
865 .body(val)
866 }
867}
868
869impl From<BytesMut> for Response {
870 fn from(val: BytesMut) -> Self {
871 Response::Ok()
872 .content_type("application/octet-stream")
873 .body(val)
874 }
875}
876
877impl<B: MessageBody> Error for Response<B> {}
878
879#[cfg(test)]
880mod tests {
881 use super::*;
882 use crate::http::header::{CONTENT_TYPE, COOKIE};
883
884 #[test]
885 fn test_take_copies_head() {
886 let mut resp = Response::NotFound()
887 .header(CONTENT_TYPE, "text/plain")
888 .reason("Nope")
889 .body("body");
890 resp.extensions_mut().insert(1u8);
891
892 let mut taken = resp.take();
893 assert_eq!(taken.status(), StatusCode::NOT_FOUND);
894 assert_eq!(taken.head().reason, Some("Nope"));
895 assert_eq!(taken.headers().get(CONTENT_TYPE).unwrap(), "text/plain");
896 assert_eq!(taken.get_body_ref(), b"body");
897 assert!(taken.extensions().get::<u8>().is_none());
898
899 *taken.status_mut() = StatusCode::OK;
901 taken.headers_mut().remove(CONTENT_TYPE);
902 resp.headers_mut()
903 .insert(COOKIE, HeaderValue::from_static("a=b"));
904 assert_eq!(resp.status(), StatusCode::NOT_FOUND);
905 assert!(resp.headers().contains_key(CONTENT_TYPE));
906 assert!(!taken.headers().contains_key(COOKIE));
907 assert_eq!(resp.extensions().get::<u8>(), Some(&1));
908 }
909
910 #[test]
911 fn test_debug() {
912 let resp = Response::Ok()
913 .header(COOKIE, HeaderValue::from_static("cookie1=value1; "))
914 .header(COOKIE, HeaderValue::from_static("cookie2=value2; "))
915 .build();
916 let dbg = format!("{resp:?}");
917 assert!(dbg.contains("Response"));
918 let dbg = format!("{:?}", resp.head());
919 assert!(dbg.contains("ResponseHead"));
920
921 let mut resp = Response::Ok();
922 resp.header(COOKIE, HeaderValue::from_static("cookie1=value1; "));
923 resp.header(COOKIE, HeaderValue::from_static("cookie2=value2; "));
924 let dbg = format!("{resp:?}");
925 assert!(dbg.contains("ResponseBuilder"));
926 }
927
928 #[cfg(feature = "cookie")]
929 #[test]
930 fn test_response_cookies() {
931 use crate::http::header::{COOKIE, SET_COOKIE};
932 use crate::http::httpmessage::HttpMessage;
933
934 let req = crate::http::test::TestRequest::default()
935 .header(COOKIE, "cookie1=value1")
936 .header(COOKIE, "cookie2=value2")
937 .build();
938 let cookies = req.cookies().unwrap();
939
940 let resp = Response::Ok()
941 .cookie(
942 coo_kie::Cookie::build(("name", "value"))
943 .domain("www.rust-lang.org")
944 .path("/test")
945 .http_only(true)
946 .max_age(time::Duration::days(1)),
947 )
948 .del_cookie(&cookies[0])
949 .build();
950
951 let mut val: Vec<_> = resp
952 .headers()
953 .get_all(SET_COOKIE)
954 .map(|v| v.to_str().unwrap().to_owned())
955 .collect();
956 val.sort();
957 assert!(val[0].starts_with("cookie1=; Max-Age=0;"));
958 assert_eq!(
959 val[1],
960 "name=value; HttpOnly; Path=/test; Domain=www.rust-lang.org; Max-Age=86400"
961 );
962 }
963
964 #[cfg(feature = "cookie")]
965 #[test]
966 fn test_update_response_cookies() {
967 let mut r = Response::Ok()
968 .cookie(coo_kie::Cookie::new("original", "val100"))
969 .build();
970
971 r.add_cookie(coo_kie::Cookie::new("cookie2", "val200"))
972 .unwrap();
973 r.add_cookie(coo_kie::Cookie::new("cookie2", "val250"))
974 .unwrap();
975 r.add_cookie(coo_kie::Cookie::new("cookie3", "val300"))
976 .unwrap();
977
978 assert_eq!(r.cookies().count(), 4);
979 r.del_cookie("cookie2");
980
981 let mut iter = r.cookies();
982 let v = iter.next().unwrap();
983 assert_eq!((v.name(), v.value()), ("original", "val100"));
984 let v = iter.next().unwrap();
985 assert_eq!((v.name(), v.value()), ("cookie3", "val300"));
986 }
987
988 #[test]
989 fn test_basic_builder() {
990 let resp = Response::Ok().header("X-TEST", "value").build();
991 assert_eq!(resp.status(), StatusCode::OK);
992 }
993
994 #[test]
995 fn test_upgrade() {
996 let resp = Response::builder(StatusCode::OK)
997 .upgrade("websocket")
998 .build();
999 assert!(resp.upgrade());
1000 assert_eq!(
1001 resp.headers().get(header::UPGRADE).unwrap(),
1002 HeaderValue::from_static("websocket")
1003 );
1004 }
1005
1006 #[test]
1007 fn test_force_close() {
1008 let resp = Response::builder(StatusCode::OK).force_close().build();
1009 assert!(!resp.keep_alive());
1010 }
1011
1012 #[test]
1013 fn test_content_type() {
1014 let resp = Response::builder(StatusCode::OK)
1015 .content_type("text/plain")
1016 .body(Body::Empty);
1017 assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "text/plain");
1018 }
1019
1020 #[test]
1021 fn test_json() {
1022 let resp = Response::builder(StatusCode::OK).json(&vec!["v1", "v2", "v3"]);
1023 let ct = resp.headers().get(CONTENT_TYPE).unwrap();
1024 assert_eq!(ct, HeaderValue::from_static("application/json"));
1025 assert_eq!(resp.get_body_ref(), b"[\"v1\",\"v2\",\"v3\"]");
1026 }
1027
1028 #[test]
1029 fn test_json_ct() {
1030 let resp = Response::builder(StatusCode::OK)
1031 .header(CONTENT_TYPE, "text/json")
1032 .json(&vec!["v1", "v2", "v3"]);
1033 let ct = resp.headers().get(CONTENT_TYPE).unwrap();
1034 assert_eq!(ct, HeaderValue::from_static("text/json"));
1035 assert_eq!(resp.get_body_ref(), b"[\"v1\",\"v2\",\"v3\"]");
1036 }
1037
1038 #[test]
1039 fn test_into_response() {
1040 let resp: Response = "test".into();
1041 assert_eq!(resp.status(), StatusCode::OK);
1042 assert_eq!(
1043 resp.headers().get(CONTENT_TYPE).unwrap(),
1044 HeaderValue::from_static("text/plain; charset=utf-8")
1045 );
1046 assert_eq!(resp.status(), StatusCode::OK);
1047 assert_eq!(resp.get_body_ref(), b"test");
1048
1049 let resp: Response = b"test".as_ref().into();
1050 assert_eq!(resp.status(), StatusCode::OK);
1051 assert_eq!(
1052 resp.headers().get(CONTENT_TYPE).unwrap(),
1053 HeaderValue::from_static("application/octet-stream")
1054 );
1055 assert_eq!(resp.status(), StatusCode::OK);
1056 assert_eq!(resp.get_body_ref(), b"test");
1057
1058 let resp: Response = "test".to_owned().into();
1059 assert_eq!(resp.status(), StatusCode::OK);
1060 assert_eq!(
1061 resp.headers().get(CONTENT_TYPE).unwrap(),
1062 HeaderValue::from_static("text/plain; charset=utf-8")
1063 );
1064 assert_eq!(resp.status(), StatusCode::OK);
1065 assert_eq!(resp.get_body_ref(), b"test");
1066
1067 let resp: Response = (&"test".to_owned()).into();
1068 assert_eq!(resp.status(), StatusCode::OK);
1069 assert_eq!(
1070 resp.headers().get(CONTENT_TYPE).unwrap(),
1071 HeaderValue::from_static("text/plain; charset=utf-8")
1072 );
1073 assert_eq!(resp.status(), StatusCode::OK);
1074 assert_eq!(resp.get_body_ref(), b"test");
1075
1076 let b = Bytes::from_static(b"test");
1077 let resp: Response = b.into();
1078 assert_eq!(resp.status(), StatusCode::OK);
1079 assert_eq!(
1080 resp.headers().get(CONTENT_TYPE).unwrap(),
1081 HeaderValue::from_static("application/octet-stream")
1082 );
1083 assert_eq!(resp.status(), StatusCode::OK);
1084 assert_eq!(resp.get_body_ref(), b"test");
1085
1086 let b = Bytes::from_static(b"test");
1087 let resp: Response = b.into();
1088 assert_eq!(resp.status(), StatusCode::OK);
1089 assert_eq!(
1090 resp.headers().get(CONTENT_TYPE).unwrap(),
1091 HeaderValue::from_static("application/octet-stream")
1092 );
1093 assert_eq!(resp.status(), StatusCode::OK);
1094 assert_eq!(resp.get_body_ref(), b"test");
1095
1096 let b = BytesMut::from("test");
1097 let resp: Response = b.into();
1098 assert_eq!(resp.status(), StatusCode::OK);
1099 assert_eq!(
1100 resp.headers().get(CONTENT_TYPE).unwrap(),
1101 HeaderValue::from_static("application/octet-stream")
1102 );
1103
1104 assert_eq!(resp.status(), StatusCode::OK);
1105 assert_eq!(resp.get_body_ref(), b"test");
1106
1107 let builder = Response::builder_from(ResponseBuilder::new(StatusCode::OK))
1108 .keep_alive()
1109 .take();
1110 let _ = builder.extensions();
1111 let resp: Response = builder.into();
1112 assert_eq!(resp.status(), StatusCode::OK);
1113 }
1114
1115 #[test]
1116 fn test_into_builder() {
1117 #[allow(unused_mut)]
1118 let mut resp: Response = "test".into();
1119 assert_eq!(resp.status(), StatusCode::OK);
1120
1121 #[cfg(feature = "cookie")]
1122 resp.add_cookie(coo_kie::Cookie::new("cookie1", "val100"))
1123 .unwrap();
1124 let (resp, _) = resp.into_parts();
1125
1126 let mut builder: ResponseBuilder = resp.head().into();
1127 let resp = builder.status(StatusCode::BAD_REQUEST).build();
1128 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
1129
1130 #[cfg(feature = "cookie")]
1131 {
1132 let cookie = resp.cookies().next().unwrap();
1133 assert_eq!((cookie.name(), cookie.value()), ("cookie1", "val100"));
1134 }
1135
1136 let mut builder: ResponseBuilder = resp.into();
1137 let resp = builder.status(StatusCode::BAD_REQUEST).build();
1138 assert_eq!(resp.status(), StatusCode::BAD_REQUEST);
1139
1140 #[cfg(feature = "cookie")]
1141 {
1142 let cookie = resp.cookies().next().unwrap();
1143 assert_eq!((cookie.name(), cookie.value()), ("cookie1", "val100"));
1144 }
1145 }
1146
1147 #[test]
1148 fn test_display() {
1149 let resp = Response::NotFound().reason(" Nope").build();
1150 assert_eq!(resp.to_string(), "Response<HTTP/1.1 404 Not Found Nope>\n");
1151 }
1152
1153 #[test]
1154 fn test_builder_invalid_headers() {
1155 let resp = Response::Ok().header("bad name", "value").build();
1156 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1157 let resp = Response::Ok().header("x-name", "bad\nvalue").build();
1158 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1159 let resp = Response::Ok().set_header("bad name", "value").build();
1160 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1161 let resp = Response::Ok().set_header("x-name", "bad\nvalue").build();
1162 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1163 let resp = Response::Ok().content_type("bad\nvalue").build();
1164 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1165
1166 let resp = Response::Ok().header("bad name", "value").json(&vec![1, 2]);
1168 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1169 }
1170
1171 #[test]
1172 fn test_json_error() {
1173 let mut map = std::collections::HashMap::new();
1174 map.insert(vec![1u8], 1);
1175 let resp = Response::Ok().json(&map);
1176 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1177 }
1178
1179 #[cfg(feature = "cookie")]
1180 #[test]
1181 fn test_cookies() {
1182 let cookie = Cookie::new("name", "value");
1183 let resp = Response::Ok().del_cookie(&cookie).build();
1184 let c = resp.cookies().next().unwrap();
1185 assert_eq!(c.name(), "name");
1186 assert_eq!(c.value(), "");
1187
1188 let resp = Response::Ok()
1189 .cookie(Cookie::new("name", "bad\nvalue"))
1190 .build();
1191 assert_eq!(resp.status(), StatusCode::INTERNAL_SERVER_ERROR);
1192
1193 let resp = Response::Ok()
1194 .cookie(Cookie::new("c1", "v1"))
1195 .cookie(Cookie::new("c2", "v2"))
1196 .build();
1197 let mut builder = ResponseBuilder::from(resp.head());
1198 let resp2 = builder.build();
1199 assert_eq!(resp2.cookies().count(), 2);
1200 let mut builder = ResponseBuilder::from(resp);
1201 let resp3 = builder.build();
1202 assert_eq!(resp3.cookies().count(), 2);
1203 }
1204}