1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
use crate::{Request, Response};
use async_std::io::BufReader;

/// Conversion into a `Response`.
pub trait IntoResponse: Send + Sized {
    /// Convert the value into a `Response`.
    fn into_response(self) -> Response;

    /// Create a new `IntoResponse` value that will respond with the given status code.
    ///
    /// ```
    /// # use tide::IntoResponse;
    /// let resp = "Hello, 404!".with_status(http::status::StatusCode::NOT_FOUND).into_response();
    /// assert_eq!(resp.status(), http::status::StatusCode::NOT_FOUND);
    /// ```
    fn with_status(self, status: http::status::StatusCode) -> WithStatus<Self> {
        WithStatus {
            inner: self,
            status,
        }
    }
}

// impl IntoResponse for () {
//     fn into_response(self) -> Response {
//         http::Response::builder()
//             .status(http::status::StatusCode::NO_CONTENT)
//             .body(Body::empty())
//             .unwrap()
//     }
// }

// impl IntoResponse for Vec<u8> {
//     fn into_response(self) -> Response {
//         http::Response::builder()
//             .status(http::status::StatusCode::OK)
//             .header("Content-Type", "application/octet-stream")
//             .body(Body::from(self))
//             .unwrap()
//     }
// }

impl IntoResponse for String {
    fn into_response(self) -> Response {
        Response::new(200)
            .set_header("Content-Type", "text/plain; charset=utf-8")
            .body_string(self)
    }
}

impl<State: Send + Sync + 'static> IntoResponse for Request<State> {
    fn into_response(self) -> Response {
        Response::new(200).body(BufReader::new(self))
    }
}

impl IntoResponse for &'_ str {
    fn into_response(self) -> Response {
        self.to_string().into_response()
    }
}

// impl IntoResponse for http::status::StatusCode {
//     fn into_response(self) -> Response {
//         http::Response::builder()
//             .status(self)
//             .body(Body::empty())
//             .unwrap()
//     }
// }

// impl<T: IntoResponse, U: IntoResponse> IntoResponse for Result<T, U> {
//     fn into_response(self) -> Response {
//         match self {
//             Ok(r) => r.into_response(),
//             Err(r) => {
//                 let res = r.into_response();
//                 if res.status().is_success() {
//                     panic!(
//                         "Attempted to yield error response with success code {:?}",
//                         res.status()
//                     )
//                 }
//                 res
//             }
//         }
//     }
// }

impl IntoResponse for Response {
    fn into_response(self) -> Response {
        self
    }
}

/// A response type that modifies the status code.
#[derive(Debug)]
pub struct WithStatus<R> {
    inner: R,
    status: http::status::StatusCode,
}

impl<R: IntoResponse> IntoResponse for WithStatus<R> {
    fn into_response(self) -> Response {
        self.inner.into_response().set_status(self.status)
    }
}