1use crate::cookies::Cookie;
4use crate::error::Error;
5use bytes::Bytes;
6use http::StatusCode;
7use serde::Serialize;
8
9pub struct Response {
11 pub status: StatusCode,
12 pub headers: http::HeaderMap,
13 pub body: Bytes,
14 cookies: Vec<Cookie>,
15}
16
17impl Response {
18 pub fn new(status: StatusCode) -> Self {
19 Self {
20 status,
21 headers: http::HeaderMap::new(),
22 body: Bytes::new(),
23 cookies: Vec::new(),
24 }
25 }
26
27 pub fn cookie(mut self, cookie: Cookie) -> Self {
29 self.cookies.push(cookie);
30 self
31 }
32
33 pub fn ok() -> Self {
34 Self::new(StatusCode::OK)
35 }
36
37 pub fn with_body(mut self, body: impl Into<Bytes>) -> Self {
38 self.body = body.into();
39 self
40 }
41
42 pub fn with_header(mut self, key: impl Into<String>, value: impl Into<String>) -> Self {
43 let key = key.into();
44 let value = value.into();
45
46 if let (Ok(header_name), Ok(header_value)) = (
48 http::HeaderName::from_bytes(key.as_bytes()),
49 http::HeaderValue::from_str(&value),
50 ) {
51 self.headers.insert(header_name, header_value);
52 } else {
53 eprintln!("Warning: Invalid header {}={}", key, value);
54 }
55 self
56 }
57
58 pub fn json<T: Serialize>(data: T) -> Self {
59 match serde_json::to_vec(&data) {
60 Ok(body) => Self::ok()
61 .with_header("content-type", "application/json")
62 .with_body(body),
63 Err(e) => {
64 eprintln!("JSON serialization error: {}", e);
65 Self::new(StatusCode::INTERNAL_SERVER_ERROR)
66 .with_header("content-type", "application/json")
67 .with_body("{\"error\":\"Internal serialization error\"}")
68 }
69 }
70 }
71
72 pub fn text(text: impl Into<String>) -> Self {
73 Self::ok()
74 .with_header("content-type", "text/plain")
75 .with_body(text.into())
76 }
77
78 pub fn from_error(error: Error) -> Self {
79 let status =
80 StatusCode::from_u16(error.status_code()).unwrap_or(StatusCode::INTERNAL_SERVER_ERROR);
81 let body = serde_json::json!({
82 "error": error.message(),
83 "status": error.status_code(),
84 });
85 let body_bytes =
86 serde_json::to_vec(&body).unwrap_or_else(|_| b"{\"error\":\"Unknown error\"}".to_vec());
87 Self::new(status)
88 .with_header("content-type", "application/json")
89 .with_body(body_bytes)
90 }
91
92 pub(crate) fn into_hyper(self) -> hyper::Response<http_body_util::Full<Bytes>> {
93 let mut builder = hyper::Response::builder().status(self.status);
94
95 for (key, value) in self.headers.iter() {
96 builder = builder.header(key, value);
97 }
98
99 for cookie in self.cookies {
101 builder = builder.header("set-cookie", cookie.to_header_value());
102 }
103
104 builder
105 .body(http_body_util::Full::new(self.body))
106 .unwrap_or_else(|e| {
107 eprintln!("Failed to build response: {}", e);
108 hyper::Response::builder()
109 .status(StatusCode::INTERNAL_SERVER_ERROR)
110 .body(http_body_util::Full::new(Bytes::from(
111 "Internal Server Error",
112 )))
113 .unwrap()
114 })
115 }
116}
117
118pub struct Json<T>(pub T);
120
121impl<T: Serialize> From<Json<T>> for Response {
122 fn from(json: Json<T>) -> Self {
123 Response::json(json.0)
124 }
125}