highnoon/responder.rs
1use crate::response::Response;
2use crate::Result;
3use hyper::{Body, StatusCode};
4use serde::Serialize;
5
6/// This trait is implemented for all the common types you can return from an endpoint
7///
8/// It's also implemented for `Response` and `hyper::Response` for compatibility.
9/// There is an implementation for `Result<R> where R: Responder` which allows fallible
10/// functions to be used as endpoints
11///
12/// ```
13/// use highnoon::{Request, Responder, Json, StatusCode};
14///
15/// fn example_1(_: Request<()>) -> impl Responder {
16/// // return status code
17/// StatusCode::NOT_FOUND
18/// }
19///
20/// fn example_2(_: Request<()>) -> impl Responder {
21/// // return strings (&str or String)
22/// "Hello World"
23/// }
24///
25/// fn example_3(_: Request<()>) -> impl Responder {
26/// // return status code with data
27/// (StatusCode::NOT_FOUND, "Not found!")
28/// }
29///
30/// fn example_4(_: Request<()>) -> impl Responder {
31/// // return JSON data - for any type implementing `serde::Serialize`
32/// Json(vec![1, 2, 3])
33/// }
34///
35/// fn example_5(_: Request<()>) -> highnoon::Result<impl Responder> {
36/// // fallible functions too
37/// // (also works the return type as `impl Responder` as long as Rust can infer
38/// // the function returns `highnoon::Result`)
39/// Ok((StatusCode::CONFLICT, "Already Exists"))
40/// }
41/// ```
42
43pub trait Responder {
44 fn into_response(self) -> Result<Response>;
45}
46
47impl Responder for StatusCode {
48 fn into_response(self) -> Result<Response> {
49 Ok(Response::status(self))
50 }
51}
52
53impl Responder for String {
54 fn into_response(self) -> Result<Response> {
55 Ok(Response::ok().body(self))
56 }
57}
58
59impl Responder for &str {
60 fn into_response(self) -> Result<Response> {
61 Ok(Response::ok().body(self.to_owned()))
62 }
63}
64
65impl Responder for &[u8] {
66 fn into_response(self) -> Result<Response> {
67 Ok(Response::ok().body(self.to_vec()))
68 }
69}
70
71impl Responder for Vec<u8> {
72 fn into_response(self) -> Result<Response> {
73 Ok(Response::ok().body(self))
74 }
75}
76
77impl<R: Responder> Responder for (StatusCode, R) {
78 fn into_response(self) -> Result<Response> {
79 let mut resp = self.1.into_response()?;
80 resp.set_status(self.0);
81 Ok(resp)
82 }
83}
84
85/// Returns `StatusCode::NotFound` for `None`, and the inner value for `Some`
86impl<R: Responder> Responder for Option<R> {
87 fn into_response(self) -> Result<Response> {
88 match self {
89 None => StatusCode::NOT_FOUND.into_response(),
90 Some(r) => r.into_response(),
91 }
92 }
93}
94
95/// A Wrapper to return a JSON payload. This can be wrapped over any `serde::Serialize` type.
96/// ```
97/// use highnoon::{Request, Responder, Json};
98/// fn returns_json(_: Request<()>) -> impl Responder {
99/// Json(vec!["an", "array"])
100/// }
101/// ```
102pub struct Json<T: Serialize>(pub T);
103
104impl<T: Serialize> Responder for Json<T> {
105 fn into_response(self) -> Result<Response> {
106 Response::ok().json(self.0)
107 }
108}
109
110/// A Wrapper to return Form data. This can be wrapped over any `serde::Serialize` type.
111pub struct Form<T: Serialize>(pub T);
112
113impl<T: Serialize> Responder for Form<T> {
114 fn into_response(self) -> Result<Response> {
115 Response::ok().form(self.0)
116 }
117}
118
119/// Identity implementation
120impl Responder for Response {
121 fn into_response(self) -> Result<Response> {
122 Ok(self)
123 }
124}
125
126/// Compatibility with the inner hyper::Response
127impl Responder for hyper::Response<Body> {
128 fn into_response(self) -> Result<Response> {
129 Ok(self.into())
130 }
131}
132
133impl<R: Responder> Responder for Result<R> {
134 fn into_response(self) -> Result<Response> {
135 self.and_then(|r| r.into_response())
136 }
137}