elif_http/response/
helpers.rs1use crate::response::{ElifResponse, ElifStatusCode};
25use serde::Serialize;
26use std::collections::HashMap;
27
28pub fn json<T: Serialize>(data: &T) -> ElifResponse {
30 ElifResponse::ok().json(data).unwrap_or_else(|err| {
31 tracing::error!("JSON serialization failed in response helper: {}", err);
32 ElifResponse::internal_server_error()
33 })
34}
35
36pub fn json_status<T: Serialize>(data: &T, status: ElifStatusCode) -> ElifResponse {
38 ElifResponse::with_status(status)
39 .json(data)
40 .unwrap_or_else(|err| {
41 tracing::error!("JSON serialization failed in json_status helper: {}", err);
42 ElifResponse::internal_server_error()
43 })
44}
45
46pub fn json_with_headers<T: Serialize>(data: &T, headers: &[(&str, &str)]) -> ElifResponse {
48 let mut response = ElifResponse::ok()
49 .json(data)
50 .unwrap_or_else(|_| ElifResponse::internal_server_error());
51
52 for (key, value) in headers {
53 response = response
54 .header(key, value)
55 .unwrap_or_else(|_| ElifResponse::internal_server_error());
56 }
57
58 response
59}
60
61pub fn redirect(url: &str) -> ElifResponse {
63 ElifResponse::redirect_temporary(url).unwrap_or_else(|_| ElifResponse::internal_server_error())
64}
65
66pub fn redirect_permanent(url: &str) -> ElifResponse {
68 ElifResponse::redirect_permanent(url).unwrap_or_else(|_| ElifResponse::internal_server_error())
69}
70
71pub fn text<S: AsRef<str>>(content: S) -> ElifResponse {
75 ElifResponse::ok().text(content.as_ref())
76}
77
78pub fn html<S: AsRef<str>>(content: S) -> ElifResponse {
82 ElifResponse::ok()
83 .text(content.as_ref())
84 .with_header("content-type", "text/html; charset=utf-8")
85}
86
87pub fn no_content() -> ElifResponse {
91 ElifResponse::no_content()
92}
93
94pub fn created<T: Serialize>(data: &T) -> ElifResponse {
98 json_status(data, ElifStatusCode::CREATED)
99}
100
101pub fn accepted<T: Serialize>(data: &T) -> ElifResponse {
105 json_status(data, ElifStatusCode::ACCEPTED)
106}
107
108pub fn bad_request<S: AsRef<str>>(message: S) -> ElifResponse {
112 let error = HashMap::from([("error", message.as_ref())]);
113 json_status(&error, ElifStatusCode::BAD_REQUEST)
114}
115
116pub fn unauthorized<S: AsRef<str>>(message: S) -> ElifResponse {
120 let error = HashMap::from([("error", message.as_ref())]);
121 json_status(&error, ElifStatusCode::UNAUTHORIZED)
122}
123
124pub fn forbidden<S: AsRef<str>>(message: S) -> ElifResponse {
128 let error = HashMap::from([("error", message.as_ref())]);
129 json_status(&error, ElifStatusCode::FORBIDDEN)
130}
131
132pub fn not_found<S: AsRef<str>>(message: S) -> ElifResponse {
136 let error = HashMap::from([("error", message.as_ref())]);
137 json_status(&error, ElifStatusCode::NOT_FOUND)
138}
139
140pub fn server_error<S: AsRef<str>>(message: S) -> ElifResponse {
144 let error = HashMap::from([("error", message.as_ref())]);
145 json_status(&error, ElifStatusCode::INTERNAL_SERVER_ERROR)
146}
147
148pub fn validation_error<T: Serialize>(errors: &T) -> ElifResponse {
152 let response_body = HashMap::from([("errors", errors)]);
153 json_status(&response_body, ElifStatusCode::UNPROCESSABLE_ENTITY)
154}
155
156#[cfg(test)]
157mod tests {
158 use super::*;
159 use serde_json::json;
160
161 #[test]
162 fn test_json_response() {
163 let data = vec!["Alice", "Bob"];
164 let response = json(&data);
165 assert_eq!(response.status_code(), ElifStatusCode::OK);
166 }
167
168 #[test]
169 fn test_json_status_response() {
170 let data = vec!["Alice"];
171 let response = json_status(&data, ElifStatusCode::CREATED);
172 assert_eq!(response.status_code(), ElifStatusCode::CREATED);
173 }
174
175 #[test]
176 fn test_redirect_response() {
177 let response = redirect("https://example.com");
178 assert_eq!(response.status_code(), ElifStatusCode::FOUND);
179 }
180
181 #[test]
182 fn test_text_response() {
183 let response = text("Hello, World!");
184 assert_eq!(response.status_code(), ElifStatusCode::OK);
185 }
186
187 #[test]
188 fn test_html_response() {
189 let response = html("<h1>Hello, World!</h1>");
190 assert_eq!(response.status_code(), ElifStatusCode::OK);
191 }
192
193 #[test]
194 fn test_no_content_response() {
195 let response = no_content();
196 assert_eq!(response.status_code(), ElifStatusCode::NO_CONTENT);
197 }
198
199 #[test]
200 fn test_created_response() {
201 let data = vec!["Alice"];
202 let response = created(&data);
203 assert_eq!(response.status_code(), ElifStatusCode::CREATED);
204 }
205
206 #[test]
207 fn test_error_responses() {
208 let bad_req = bad_request("Invalid input");
209 assert_eq!(bad_req.status_code(), ElifStatusCode::BAD_REQUEST);
210
211 let unauthorized_resp = unauthorized("Please login");
212 assert_eq!(
213 unauthorized_resp.status_code(),
214 ElifStatusCode::UNAUTHORIZED
215 );
216
217 let forbidden_resp = forbidden("Access denied");
218 assert_eq!(forbidden_resp.status_code(), ElifStatusCode::FORBIDDEN);
219
220 let not_found_resp = not_found("User not found");
221 assert_eq!(not_found_resp.status_code(), ElifStatusCode::NOT_FOUND);
222
223 let server_err = server_error("Database connection failed");
224 assert_eq!(
225 server_err.status_code(),
226 ElifStatusCode::INTERNAL_SERVER_ERROR
227 );
228 }
229
230 #[test]
231 fn test_validation_error() {
232 let errors = json!({
233 "name": ["The name field is required"],
234 "email": ["The email must be a valid email address"]
235 });
236
237 let response = validation_error(&errors);
238 assert_eq!(response.status_code(), ElifStatusCode::UNPROCESSABLE_ENTITY);
239 }
240
241 #[test]
242 fn test_json_with_headers() {
243 let data = vec!["Alice", "Bob"];
244 let headers = [("X-Total-Count", "2"), ("X-Custom", "value")];
245 let response = json_with_headers(&data, &headers);
246 assert_eq!(response.status_code(), ElifStatusCode::OK);
247 }
248}