rustfs_rsc/client/
executor.rs1use bytes::Bytes;
2use hyper::header::{HeaderName, HeaderValue};
3use hyper::{HeaderMap, Method};
4use reqwest::Response;
5
6use super::{Minio, QueryMap};
7use crate::data::Data;
8use crate::datatype::{FromXml, ToXml};
9use crate::error::{Error, Result, S3Error};
10use crate::utils::md5sum_hash;
11
12pub struct BaseExecutor<'a> {
43 method: Method,
44 region: String,
45 bucket_name: Option<String>,
46 object_name: Option<String>,
47 body: Data<Error>,
48 headers: HeaderMap,
49 querys: QueryMap,
50 client: &'a Minio,
51 build_err: Result<()>,
52}
53
54impl<'a> BaseExecutor<'a> {
55 pub fn new(method: Method, client: &'a Minio) -> Self {
56 return Self {
57 method,
58 region: client.region().to_string(),
59 bucket_name: None,
60 object_name: None,
61 body: Default::default(),
62 headers: HeaderMap::new(),
63 client,
64 querys: QueryMap::new(),
65 build_err: Ok(()),
66 };
67 }
68
69 pub fn method(mut self, method: Method) -> Self {
71 self.method = method;
72 self
73 }
74
75 pub fn bucket_name<T: Into<String>>(mut self, name: T) -> Self {
77 self.bucket_name = Some(name.into());
78 self
79 }
80
81 pub fn object_name<T: Into<String>>(mut self, name: T) -> Self {
83 self.object_name = Some(name.into());
84 self
85 }
86
87 pub fn region<T: Into<String>>(mut self, region: T) -> Self {
89 self.region = region.into();
90 self
91 }
92
93 pub fn body<B: Into<Data<Error>>>(mut self, body: B) -> Self {
95 self.body = body.into();
96 self
97 }
98
99 pub(crate) fn xml<'de, S>(mut self, xml: &'de S) -> Self
101 where
102 S: ToXml,
103 {
104 let xml = match xml.to_xml() {
105 Ok(xml) => xml,
106 Err(e) => {
107 self.build_err = Err(e);
108 return self;
109 }
110 };
111 let body = Bytes::from(xml);
112 let md5 = md5sum_hash(&body);
113 self.body(body).header("Content-MD5", md5)
114 }
115
116 pub fn headers(mut self, header: HeaderMap) -> Self {
118 self.headers = header;
119 self
120 }
121
122 pub fn header<K, V>(mut self, key: K, value: V) -> Self
124 where
125 HeaderName: TryFrom<K>,
126 <HeaderName as TryFrom<K>>::Error: Into<crate::error::Error>,
127 HeaderValue: TryFrom<V>,
128 <HeaderValue as TryFrom<V>>::Error: Into<crate::error::Error>,
129 {
130 let key = <HeaderName as TryFrom<K>>::try_from(key).map_err(Into::into);
131 let value = <HeaderValue as TryFrom<V>>::try_from(value).map_err(Into::into);
132 match (key, value) {
133 (Ok(key), Ok(val)) => {
134 self.headers.insert(key, val);
135 }
136 (Err(e), _) => self.build_err = Err(e),
137 (_, Err(e)) => self.build_err = Err(e),
138 };
139 self
140 }
141
142 #[inline]
144 pub fn headers_merge(mut self, header: HeaderMap) -> Self {
145 self.headers.extend(header);
146 self
147 }
148
149 #[inline]
151 pub fn headers_merge2(self, header: Option<HeaderMap>) -> Self {
152 if let Some(header) = header {
153 self.headers_merge(header)
154 } else {
155 self
156 }
157 }
158
159 pub fn querys(mut self, querys: QueryMap) -> Self {
161 self.querys = querys;
162 self
163 }
164
165 pub fn querys_merge(mut self, querys: QueryMap) -> Self {
167 self.querys.merge(querys);
168 self
169 }
170
171 pub fn query<K: Into<String>, V: Into<String>>(mut self, key: K, value: V) -> Self {
173 self.querys.insert(key.into(), value.into());
174 self
175 }
176
177 pub fn query_string(mut self, query_str: &str) -> Self {
179 self.querys.merge_str(query_str);
180 self
181 }
182
183 pub fn apply<F>(self, apply: F) -> Self
184 where
185 F: FnOnce(Self) -> Self,
186 {
187 apply(self)
188 }
189
190 pub async fn send(self) -> Result<Response> {
194 self.build_err?;
195 let query = self.querys.to_query_string();
196 self.client
197 ._execute(
198 self.method,
199 &self.region,
200 self.bucket_name,
201 self.object_name,
202 self.body,
203 Some(self.headers),
204 Some(query),
205 )
206 .await
207 }
208
209 pub async fn send_ok(self) -> Result<Response> {
213 let res = self.send().await?;
214 if res.status().is_success() {
215 Ok(res)
216 } else {
217 let text = res.text().await?;
218 let s: S3Error = text.as_str().try_into()?;
219 Err(s)?
220 }
221 }
222
223 pub async fn send_text_ok(self) -> Result<String> {
227 let res = self.send_ok().await?;
228 let text = res.text().await?;
229 Ok(text)
230 }
231
232 pub(crate) async fn send_xml_ok<T>(self) -> Result<T>
236 where
237 T: FromXml,
238 {
239 self.send_text_ok()
240 .await
241 .map(T::from_xml)?
242 .map_err(Into::into)
243 }
244}