actori_http/
response.rs

1//! Http response
2use std::cell::{Ref, RefMut};
3use std::convert::TryFrom;
4use std::future::Future;
5use std::pin::Pin;
6use std::task::{Context, Poll};
7use std::{fmt, str};
8
9use bytes::{Bytes, BytesMut};
10use futures_core::Stream;
11use serde::Serialize;
12use serde_json;
13
14use crate::body::{Body, BodyStream, MessageBody, ResponseBody};
15use crate::cookie::{Cookie, CookieJar};
16use crate::error::Error;
17use crate::extensions::Extensions;
18use crate::header::{Header, IntoHeaderValue};
19use crate::http::header::{self, HeaderName, HeaderValue};
20use crate::http::{Error as HttpError, HeaderMap, StatusCode};
21use crate::message::{BoxedResponseHead, ConnectionType, ResponseHead};
22
23/// An HTTP Response
24pub struct Response<B = Body> {
25    head: BoxedResponseHead,
26    body: ResponseBody<B>,
27    error: Option<Error>,
28}
29
30impl Response<Body> {
31    /// Create http response builder with specific status.
32    #[inline]
33    pub fn build(status: StatusCode) -> ResponseBuilder {
34        ResponseBuilder::new(status)
35    }
36
37    /// Create http response builder
38    #[inline]
39    pub fn build_from<T: Into<ResponseBuilder>>(source: T) -> ResponseBuilder {
40        source.into()
41    }
42
43    /// Constructs a response
44    #[inline]
45    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]
55    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
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
78impl<B> Response<B> {
79    /// Constructs a response with body
80    #[inline]
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
91    pub fn head(&self) -> &ResponseHead {
92        &*self.head
93    }
94
95    #[inline]
96    /// Mutable reference to a http message part of the response
97    pub fn head_mut(&mut self) -> &mut ResponseHead {
98        &mut *self.head
99    }
100
101    /// The source `error` for this response
102    #[inline]
103    pub fn error(&self) -> Option<&Error> {
104        self.error.as_ref()
105    }
106
107    /// Get the response status code
108    #[inline]
109    pub fn status(&self) -> StatusCode {
110        self.head.status
111    }
112
113    /// Set the `StatusCode` for this response
114    #[inline]
115    pub fn status_mut(&mut self) -> &mut StatusCode {
116        &mut self.head.status
117    }
118
119    /// Get the headers from the response
120    #[inline]
121    pub fn headers(&self) -> &HeaderMap {
122        &self.head.headers
123    }
124
125    /// Get a mutable reference to the headers
126    #[inline]
127    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]
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]
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]
153    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]
178    pub fn upgrade(&self) -> bool {
179        self.head.upgrade()
180    }
181
182    /// Keep-alive status for this connection
183    pub fn keep_alive(&self) -> bool {
184        self.head.keep_alive()
185    }
186
187    /// Responses extensions
188    #[inline]
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]
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]
201    pub fn body(&self) -> &ResponseBody<B> {
202        &self.body
203    }
204
205    /// Set a body
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
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
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
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
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
262    pub fn take_body(&mut self) -> ResponseBody<B> {
263        self.body.take_body()
264    }
265}
266
267impl<B: MessageBody> fmt::Debug for Response<B> {
268    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
285impl Future for Response {
286    type Output = Result<Response, Error>;
287
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
297pub struct CookieIter<'a> {
298    iter: header::GetAll<'a>,
299}
300
301impl<'a> Iterator for CookieIter<'a> {
302    type Item = Cookie<'a>;
303
304    #[inline]
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.
319pub struct ResponseBuilder {
320    head: Option<BoxedResponseHead>,
321    err: Option<HttpError>,
322    cookies: Option<CookieJar>,
323}
324
325impl ResponseBuilder {
326    #[inline]
327    /// Create response builder
328    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]
338    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 actori_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)]
359    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 actori_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    /// ```
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 actori_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    /// ```
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]
437    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]
446    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]
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]
467    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]
476    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]
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]
503    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 actori_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    /// ```
525    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 actori_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    /// ```
551    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.
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.
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]
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]
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.
604    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.
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.
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.
650    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.
657    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.
679    pub fn finish(&mut self) -> Response {
680        self.body(Body::Empty)
681    }
682
683    /// This method construct new `ResponseBuilder`
684    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]
694fn 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.
705impl<B> From<Response<B>> for ResponseBuilder {
706    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`
728impl<'a> From<&'a ResponseHead> for ResponseBuilder {
729    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
762impl Future for ResponseBuilder {
763    type Output = Result<Response, Error>;
764
765    fn poll(mut self: Pin<&mut Self>, _: &mut Context<'_>) -> Poll<Self::Output> {
766        Poll::Ready(Ok(self.finish()))
767    }
768}
769
770impl fmt::Debug for ResponseBuilder {
771    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
790impl<I: Into<Response>, E: Into<Error>> From<Result<I, E>> for Response {
791    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
799impl From<ResponseBuilder> for Response {
800    fn from(mut builder: ResponseBuilder) -> Self {
801        builder.finish()
802    }
803}
804
805impl From<&'static str> for Response {
806    fn from(val: &'static str) -> Self {
807        Response::Ok()
808            .content_type("text/plain; charset=utf-8")
809            .body(val)
810    }
811}
812
813impl From<&'static [u8]> for Response {
814    fn from(val: &'static [u8]) -> Self {
815        Response::Ok()
816            .content_type("application/octet-stream")
817            .body(val)
818    }
819}
820
821impl From<String> for Response {
822    fn from(val: String) -> Self {
823        Response::Ok()
824            .content_type("text/plain; charset=utf-8")
825            .body(val)
826    }
827}
828
829impl<'a> From<&'a String> for Response {
830    fn from(val: &'a String) -> Self {
831        Response::Ok()
832            .content_type("text/plain; charset=utf-8")
833            .body(val)
834    }
835}
836
837impl From<Bytes> for Response {
838    fn from(val: Bytes) -> Self {
839        Response::Ok()
840            .content_type("application/octet-stream")
841            .body(val)
842    }
843}
844
845impl From<BytesMut> for Response {
846    fn from(val: BytesMut) -> Self {
847        Response::Ok()
848            .content_type("application/octet-stream")
849            .body(val)
850    }
851}
852
853#[cfg(test)]
854mod tests {
855    use super::*;
856    use crate::body::Body;
857    use crate::http::header::{HeaderValue, CONTENT_TYPE, COOKIE, SET_COOKIE};
858
859    #[test]
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]
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]
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]
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]
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]
946    fn test_force_close() {
947        let resp = Response::build(StatusCode::OK).force_close().finish();
948        assert!(!resp.keep_alive())
949    }
950
951    #[test]
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]
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]
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]
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]
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]
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]
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]
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}