finchers_core/output/
responder.rs1use std::borrow::Cow;
2use std::fmt;
3
4use bytes::Bytes;
5use either::Either;
6use http::header::HeaderValue;
7use http::{header, Response};
8
9use super::body::ResponseBody;
10use error::Error;
11use input::Input;
12
13const TEXT_PLAIN: &str = "text/plain; charset=utf-8";
14
15pub type Output = Response<ResponseBody>;
17
18pub trait Responder {
20 fn respond(self, input: &Input) -> Result<Output, Error>;
22}
23
24impl<T> Responder for Response<T>
25where
26 T: Into<ResponseBody>,
27{
28 fn respond(self, _: &Input) -> Result<Output, Error> {
29 Ok(self.map(Into::into))
30 }
31}
32
33impl Responder for &'static str {
34 fn respond(self, _: &Input) -> Result<Output, Error> {
35 Ok(make_response(Bytes::from_static(self.as_bytes()), TEXT_PLAIN))
36 }
37}
38
39impl Responder for String {
40 fn respond(self, _: &Input) -> Result<Output, Error> {
41 Ok(make_response(Bytes::from(self), TEXT_PLAIN))
42 }
43}
44
45impl Responder for Cow<'static, str> {
46 fn respond(self, _: &Input) -> Result<Output, Error> {
47 let body = match self {
48 Cow::Borrowed(s) => Bytes::from_static(s.as_bytes()),
49 Cow::Owned(s) => Bytes::from(s),
50 };
51 Ok(make_response(body, TEXT_PLAIN))
52 }
53}
54
55impl<T, E> Responder for Result<T, E>
56where
57 T: Responder,
58 E: Into<Error>,
59{
60 fn respond(self, input: &Input) -> Result<Output, Error> {
61 self.map_err(Into::<Error>::into)?.respond(input).map_err(Into::into)
62 }
63}
64
65impl<L, R> Responder for Either<L, R>
66where
67 L: Responder,
68 R: Responder,
69{
70 fn respond(self, input: &Input) -> Result<Output, Error> {
71 match self {
72 Either::Left(l) => l.respond(input),
73 Either::Right(r) => r.respond(input),
74 }
75 }
76}
77
78#[derive(Debug)]
82pub struct Debug {
83 value: Box<fmt::Debug + Send + 'static>,
84 pretty: bool,
85}
86
87impl Debug {
88 pub fn new<T>(value: T) -> Debug
91 where
92 T: fmt::Debug + Send + 'static,
93 {
94 Debug {
95 value: Box::new(value),
96 pretty: false,
97 }
98 }
99
100 pub fn pretty(mut self, enabled: bool) -> Self {
102 self.pretty = enabled;
103 self
104 }
105}
106
107impl Responder for Debug {
108 fn respond(self, _: &Input) -> Result<Output, Error> {
109 let body = if self.pretty {
110 format!("{:#?}", self.value)
111 } else {
112 format!("{:?}", self.value)
113 };
114
115 let mut response = Response::new(ResponseBody::once(body));
116 content_type(&mut response, TEXT_PLAIN);
117 content_length(&mut response);
118
119 Ok(response)
120 }
121}
122
123fn make_response(body: Bytes, m: &'static str) -> Output {
124 let mut response = Response::new(ResponseBody::once(body));
125 content_type(&mut response, m);
126 content_length(&mut response);
127 response
128}
129
130fn content_type<T>(response: &mut Response<T>, value: &'static str) {
131 response
132 .headers_mut()
133 .insert(header::CONTENT_TYPE, HeaderValue::from_static(value));
134}
135
136fn content_length(response: &mut Response<ResponseBody>) {
137 if let Some(body_len) = response.body().len() {
138 response.headers_mut().insert(header::CONTENT_LENGTH, unsafe {
139 HeaderValue::from_shared_unchecked(Bytes::from(body_len.to_string()))
140 });
141 }
142}