tako_rs_core/
responder.rs1use std::borrow::Cow;
25use std::convert::Infallible;
26
27use bytes::Bytes;
28use http::HeaderMap;
29use http::StatusCode;
30use http::header::HeaderName;
31use http::header::HeaderValue;
32use http_body_util::Full;
33
34use crate::body::TakoBody;
35use crate::types::Response;
36
37pub const NOT_FOUND: (StatusCode, &str) = (StatusCode::NOT_FOUND, "Not Found");
42
43#[doc(alias = "response")]
74pub trait Responder {
75 fn into_response(self) -> Response;
77}
78
79pub use Responder as IntoResponse;
84
85impl Responder for Response {
86 fn into_response(self) -> Response {
87 self
88 }
89}
90
91impl Responder for TakoBody {
92 fn into_response(self) -> Response {
93 Response::new(self)
94 }
95}
96
97impl Responder for &'static str {
98 fn into_response(self) -> Response {
99 Response::new(TakoBody::full(Full::from(Bytes::from_static(
100 self.as_bytes(),
101 ))))
102 }
103}
104
105impl Responder for String {
106 fn into_response(self) -> Response {
107 Response::new(TakoBody::full(Full::from(Bytes::from(self))))
108 }
109}
110
111impl Responder for () {
112 fn into_response(self) -> Response {
113 Response::new(TakoBody::empty())
114 }
115}
116
117impl Responder for Infallible {
118 fn into_response(self) -> Response {
119 match self {}
120 }
121}
122
123impl Responder for (StatusCode, &'static str) {
124 fn into_response(self) -> Response {
125 let (status, body) = self;
126 let mut res = Response::new(TakoBody::full(Full::from(Bytes::from_static(
127 body.as_bytes(),
128 ))));
129 *res.status_mut() = status;
130 res
131 }
132}
133
134impl Responder for (StatusCode, String) {
135 fn into_response(self) -> Response {
136 let (status, body) = self;
137 let mut res = Response::new(TakoBody::full(Full::from(Bytes::from(body))));
138 *res.status_mut() = status;
139 res
140 }
141}
142
143impl Responder for (StatusCode, Vec<u8>) {
144 fn into_response(self) -> Response {
145 let (status, body) = self;
146 let mut res = Response::new(TakoBody::full(Full::from(Bytes::from(body))));
147 *res.status_mut() = status;
148 res
149 }
150}
151
152impl Responder for Bytes {
153 fn into_response(self) -> Response {
154 Response::new(TakoBody::full(Full::from(self)))
155 }
156}
157
158impl Responder for Vec<u8> {
159 fn into_response(self) -> Response {
160 Response::new(TakoBody::full(Full::from(Bytes::from(self))))
161 }
162}
163
164impl Responder for Cow<'static, str> {
165 fn into_response(self) -> Response {
166 match self {
167 Cow::Borrowed(s) => {
168 Response::new(TakoBody::full(Full::from(Bytes::from_static(s.as_bytes()))))
169 }
170 Cow::Owned(s) => Response::new(TakoBody::full(Full::from(Bytes::from(s)))),
171 }
172 }
173}
174
175impl Responder for serde_json::Value {
176 fn into_response(self) -> Response {
177 match serde_json::to_vec(&self) {
178 Ok(buf) => {
179 let mut res = Response::new(TakoBody::full(Full::from(Bytes::from(buf))));
180 res.headers_mut().insert(
181 http::header::CONTENT_TYPE,
182 HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
183 );
184 res
185 }
186 Err(err) => {
187 let mut res = Response::new(TakoBody::from(err.to_string()));
188 *res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
189 res.headers_mut().insert(
190 http::header::CONTENT_TYPE,
191 HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
192 );
193 res
194 }
195 }
196 }
197}
198
199impl Responder for (StatusCode, HeaderMap, TakoBody) {
200 fn into_response(self) -> Response {
201 let (status, headers, body) = self;
202 let mut res = Response::new(body);
203 *res.status_mut() = status;
204 *res.headers_mut() = headers;
205 res
206 }
207}
208
209impl Responder for (StatusCode, HeaderMap) {
210 fn into_response(self) -> Response {
211 let (status, headers) = self;
212 let mut res = Response::new(TakoBody::empty());
213 *res.status_mut() = status;
214 *res.headers_mut() = headers;
215 res
216 }
217}
218
219impl Responder for HeaderMap {
220 fn into_response(self) -> Response {
221 let mut res = Response::new(TakoBody::empty());
222 *res.headers_mut() = self;
223 res
224 }
225}
226
227impl Responder for StatusCode {
228 fn into_response(self) -> Response {
229 let mut res = Response::new(TakoBody::empty());
230 *res.status_mut() = self;
231 res
232 }
233}
234
235pub struct StaticHeaders<const N: usize>(pub [(HeaderName, &'static str); N]);
236
237impl<const N: usize> Responder for (StatusCode, StaticHeaders<N>) {
238 fn into_response(self) -> Response {
239 let (status, StaticHeaders(headers)) = self;
240 let mut res = Response::new(TakoBody::empty());
241 *res.status_mut() = status;
242
243 for (name, value) in headers {
244 res
245 .headers_mut()
246 .append(name, HeaderValue::from_static(value));
247 }
248 res
249 }
250}
251
252impl Responder for anyhow::Error {
253 fn into_response(self) -> Response {
254 let mut res = Response::new(TakoBody::from(self.to_string()));
255 *res.status_mut() = StatusCode::INTERNAL_SERVER_ERROR;
256 res.headers_mut().insert(
257 http::header::CONTENT_TYPE,
258 HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
259 );
260 res
261 }
262}
263
264impl ResponderError for anyhow::Error {}
265
266impl<T, E> Responder for Result<T, E>
276where
277 T: Responder,
278 E: ResponderError,
279{
280 fn into_response(self) -> Response {
281 match self {
282 Ok(ok) => ok.into_response(),
283 Err(err) => err.into_response(),
284 }
285 }
286}
287
288pub trait ResponderError: Responder {}