1use bytes::Bytes;
2use http_body_util::Full;
3
4pub struct HttpResponse {
6 status: u16,
7 body: String,
8 headers: Vec<(String, String)>,
9}
10
11pub type Response = Result<HttpResponse, HttpResponse>;
13
14impl HttpResponse {
15 pub fn new() -> Self {
16 Self {
17 status: 200,
18 body: String::new(),
19 headers: Vec::new(),
20 }
21 }
22
23 pub fn text(body: impl Into<String>) -> Self {
25 Self {
26 status: 200,
27 body: body.into(),
28 headers: vec![("Content-Type".to_string(), "text/plain".to_string())],
29 }
30 }
31
32 pub fn json(body: serde_json::Value) -> Self {
34 Self {
35 status: 200,
36 body: body.to_string(),
37 headers: vec![("Content-Type".to_string(), "application/json".to_string())],
38 }
39 }
40
41 pub fn status(mut self, status: u16) -> Self {
43 self.status = status;
44 self
45 }
46
47 pub fn header(mut self, name: impl Into<String>, value: impl Into<String>) -> Self {
49 self.headers.push((name.into(), value.into()));
50 self
51 }
52
53 pub fn ok(self) -> Response {
55 Ok(self)
56 }
57
58 pub fn into_hyper(self) -> hyper::Response<Full<Bytes>> {
60 let mut builder = hyper::Response::builder().status(self.status);
61
62 for (name, value) in self.headers {
63 builder = builder.header(name, value);
64 }
65
66 builder
67 .body(Full::new(Bytes::from(self.body)))
68 .unwrap()
69 }
70}
71
72impl Default for HttpResponse {
73 fn default() -> Self {
74 Self::new()
75 }
76}
77
78pub trait ResponseExt {
80 fn status(self, code: u16) -> Self;
81 fn header(self, name: impl Into<String>, value: impl Into<String>) -> Self;
82}
83
84impl ResponseExt for Response {
85 fn status(self, code: u16) -> Self {
86 self.map(|r| r.status(code))
87 }
88
89 fn header(self, name: impl Into<String>, value: impl Into<String>) -> Self {
90 self.map(|r| r.header(name, value))
91 }
92}