musdk_common/function/
response.rs1use std::{borrow::Cow, collections::HashMap};
2
3use borsh::{BorshDeserialize, BorshSerialize};
4
5use crate::http_client::{
6 header::{BINARY_CONTENT_TYPE, CONTENT_TYPE_HEADER, STRING_CONTENT_TYPE},
7 Header, Status,
8};
9
10#[derive(Debug, BorshSerialize, BorshDeserialize)]
11pub struct Response<'a> {
12 pub status: Status,
13 pub headers: Vec<Header<'a>>,
14 pub body: Cow<'a, [u8]>,
15}
16
17impl<'a> Response<'a> {
18 pub fn builder() -> ResponseBuilder<'a> {
20 ResponseBuilder::default()
21 }
22}
23
24pub struct ResponseBuilder<'a> {
25 status: Status,
26 headers: HashMap<Cow<'a, str>, Header<'a>>,
27}
28
29impl<'a> ResponseBuilder<'a> {
30 pub fn new() -> Self {
31 ResponseBuilder {
32 status: Status::Ok,
33 headers: HashMap::new(),
34 }
35 }
36
37 pub fn status(mut self, status: Status) -> Self {
38 self.status = status;
39 self
40 }
41
42 pub fn content_type(mut self, content_type: Cow<'a, str>) -> Self {
43 let header = Header {
44 name: Cow::Borrowed(CONTENT_TYPE_HEADER),
45 value: content_type,
46 };
47
48 self.headers.remove(&header.name);
49 self.headers.insert(header.name.clone(), header);
50 self
51 }
52
53 fn has_content_type(&self) -> bool {
54 self.headers
55 .contains_key(&Cow::Borrowed(CONTENT_TYPE_HEADER))
56 }
57
58 pub fn header(mut self, header: Header<'a>) -> Self {
60 let name: Cow<'a, str> = header.name.to_lowercase().into();
61 self.headers.remove(&name);
62 self.headers.insert(name, header);
63 self
64 }
65
66 pub fn headers(self, headers: Vec<Header<'a>>) -> Self {
67 headers.into_iter().fold(self, Self::header)
68 }
69
70 pub fn no_body(self) -> Response<'a> {
71 Response {
72 status: self.status,
73 headers: self.headers.into_values().collect(),
74 body: Cow::Borrowed(&[]),
75 }
76 }
77
78 pub fn body_from_slice(mut self, slice: &'a [u8]) -> Response<'a> {
79 if !self.has_content_type() {
80 self = self.content_type(Cow::Borrowed(BINARY_CONTENT_TYPE));
81 }
82
83 Response {
84 status: self.status,
85 headers: self.headers.into_values().collect(),
86 body: Cow::Borrowed(slice),
87 }
88 }
89
90 pub fn body_from_vec(mut self, vec: Vec<u8>) -> Response<'a> {
91 if !self.has_content_type() {
92 self = self.content_type(Cow::Borrowed(BINARY_CONTENT_TYPE));
93 }
94
95 Response {
96 status: self.status,
97 headers: self.headers.into_values().collect(),
98 body: Cow::Owned(vec),
99 }
100 }
101
102 pub fn body_from_string(mut self, string: String) -> Response<'a> {
103 if !self.has_content_type() {
104 self = self.content_type(Cow::Borrowed(STRING_CONTENT_TYPE));
105 }
106
107 Response {
108 status: self.status,
109 headers: self.headers.into_values().collect(),
110 body: Cow::Owned(string.as_bytes().to_vec()),
111 }
112 }
113
114 pub fn body_from_str(mut self, str: &'a str) -> Response<'a> {
115 if !self.has_content_type() {
116 self = self.content_type(Cow::Borrowed(STRING_CONTENT_TYPE));
117 }
118
119 Response {
120 status: self.status,
121 headers: self.headers.into_values().collect(),
122 body: Cow::Borrowed(str.as_bytes()),
123 }
124 }
125}
126
127impl<'a> Default for ResponseBuilder<'a> {
128 fn default() -> Self {
129 Self::new()
130 }
131}