1use http::{Response, Version};
2
3use crate::http_utils::IntoRawBytes;
4
5pub type RawResponse = Response<Vec<u8>>;
6
7pub trait IntoResponse {
10 fn response(self) -> RawResponse;
11}
12
13pub trait Action {
17 fn action(self) -> Option<RawResponse>;
18}
19
20impl<T> Action for T
21where
22 T: IntoResponse,
23{
24 fn action(self) -> Option<RawResponse> {
25 Some(self.response())
26 }
27}
28
29impl<T> Action for Response<T>
30where
31 T: IntoRawBytes,
32{
33 fn action(self) -> Option<RawResponse> {
34 Some(self.map(IntoRawBytes::into_raw_bytes))
35 }
36}
37
38impl Action for () {
39 fn action(self) -> Option<RawResponse> {
40 None
41 }
42}
43
44impl<T> Action for Option<T>
45where
46 T: Action,
47{
48 fn action(self) -> Option<RawResponse> {
49 self.and_then(Action::action)
50 }
51}
52
53impl<T, E> Action for Result<T, E>
54where
55 T: Action,
56 E: Action,
57{
58 fn action(self) -> Option<RawResponse> {
59 match self {
60 Ok(v) => v.action(),
61 Err(e) => e.action(),
62 }
63 }
64}
65
66impl IntoResponse for u16 {
67 fn response(self) -> RawResponse {
68 Response::builder()
69 .version(Version::HTTP_11)
70 .status(self)
71 .header("Content-Type", "text/plain; charset=UTF-8")
72 .header("Content-Length", "0")
73 .body(Vec::new())
74 .expect("Failed to build request")
75 }
76}
77
78pub struct Raw(Vec<u8>);
81
82impl IntoResponse for Raw {
83 fn response(self) -> RawResponse {
84 Response::builder()
85 .version(Version::HTTP_11)
86 .status(200)
87 .header("Content-Type", "application/x-binary")
88 .header("Content-Length", format!("{}", self.0.len()))
89 .body(self.0)
90 .unwrap()
91 }
92}
93
94pub struct Plain(pub String);
96
97impl IntoResponse for Plain {
98 fn response(self) -> RawResponse {
99 let bytes = self.0.into_bytes();
100
101 Response::builder()
102 .version(Version::HTTP_11)
103 .status(200)
104 .header("Content-Type", "text/plain; charset=utf-8")
105 .header("Content-Length", format!("{}", bytes.len()))
106 .body(bytes)
107 .unwrap()
108 }
109}
110
111pub struct Html(pub String);
113
114impl IntoResponse for Html {
115 fn response(self) -> RawResponse {
116 let bytes = self.0.into_bytes();
117
118 Response::builder()
119 .version(Version::HTTP_11)
120 .status(200)
121 .header("Content-Type", "text/html; charset=utf-8")
122 .header("Content-Length", format!("{}", bytes.len()))
123 .body(bytes)
124 .unwrap()
125 }
126}
127
128pub struct Css(pub String);
130
131impl IntoResponse for Css {
132 fn response(self) -> RawResponse {
133 let bytes = self.0.into_bytes();
134
135 Response::builder()
136 .version(Version::HTTP_11)
137 .status(200)
138 .header("Content-Type", "text/css; charset=utf-8")
139 .header("Content-Length", format!("{}", bytes.len()))
140 .body(bytes)
141 .unwrap()
142 }
143}
144
145pub struct Js(pub String);
147
148impl IntoResponse for Js {
149 fn response(self) -> RawResponse {
150 let bytes = self.0.into_bytes();
151
152 Response::builder()
153 .version(Version::HTTP_11)
154 .status(200)
155 .header("Content-Type", "text/javascript; charset=utf-8")
156 .header("Content-Length", format!("{}", bytes.len()))
157 .body(bytes)
158 .unwrap()
159 }
160}