1use crate::client::{Client, ParamType};
2use std::collections::HashMap;
3use crate::services::AppwriteException;
4use crate::models;
5use serde_json::json;
6use std::io::Read;
7
8#[derive(Clone)]
9pub struct Storage {
10 client: Client
11}
12
13impl Storage {
14 pub fn new(client: &Client) -> Self {
15 Self {
16 client: client.clone()
17 }
18 }
19
20 pub fn list_buckets(&self, search: Option<&str>, limit: Option<i64>, offset: Option<i64>, cursor: Option<&str>, cursor_direction: Option<&str>, order_type: Option<&str>) -> Result<models::BucketList, AppwriteException> {
23 let path = "/storage/buckets";
24 let headers: HashMap<String, String> = [
25 ("content-type".to_string(), "application/json".to_string()),
26 ].iter().cloned().collect();
27
28 let search:&str = match search {
29 Some(data) => data,
30 None => ""
31 };
32
33 let cursor:&str = match cursor {
34 Some(data) => data,
35 None => ""
36 };
37
38 let cursor_direction:&str = match cursor_direction {
39 Some(data) => data,
40 None => ""
41 };
42
43 let order_type:&str = match order_type {
44 Some(data) => data,
45 None => ""
46 };
47
48 let params: HashMap<String, ParamType> = [
49 ("search".to_string(), ParamType::String(search.to_string())),
50 ("limit".to_string(), ParamType::OptionalNumber(limit)),
51 ("offset".to_string(), ParamType::OptionalNumber(offset)),
52 ("cursor".to_string(), ParamType::String(cursor.to_string())),
53 ("cursorDirection".to_string(), ParamType::String(cursor_direction.to_string())),
54 ("orderType".to_string(), ParamType::String(order_type.to_string())),
55 ].iter().cloned().collect();
56
57 let response = self.client.clone().call("GET", &path, Some(headers), Some(params) );
58
59 let processedResponse:models::BucketList = match response {
60 Ok(r) => {
61 match r.json() {
62 Ok(json) => json,
63 Err(e) => {
64 return Err(AppwriteException::new(format!("Error parsing response json: {}", e), 0, "".to_string()));
65 }
66 }
67 }
68 Err(e) => {
69 return Err(e);
70 }
71 };
72
73 Ok(processedResponse)
74 }
75
76 pub fn create_bucket(&self, bucket_id: &str, name: &str, permission: &str, read: Option<&[&str]>, write: Option<&[&str]>, enabled: Option<bool>, maximum_file_size: Option<i64>, allowed_file_extensions: Option<&[&str]>, encryption: Option<bool>, antivirus: Option<bool>) -> Result<models::Bucket, AppwriteException> {
78 let path = "/storage/buckets";
79 let headers: HashMap<String, String> = [
80 ("content-type".to_string(), "application/json".to_string()),
81 ].iter().cloned().collect();
82
83 let read:&[&str] = match read {
84 Some(data) => data,
85 None => &[]
86 };
87
88 let write:&[&str] = match write {
89 Some(data) => data,
90 None => &[]
91 };
92
93 let allowed_file_extensions:&[&str] = match allowed_file_extensions {
94 Some(data) => data,
95 None => &[]
96 };
97
98 let params: HashMap<String, ParamType> = [
99 ("bucketId".to_string(), ParamType::String(bucket_id.to_string())),
100 ("name".to_string(), ParamType::String(name.to_string())),
101 ("permission".to_string(), ParamType::String(permission.to_string())),
102 ("read".to_string(), ParamType::Array(read.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
103 ("write".to_string(), ParamType::Array(write.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
104 ("enabled".to_string(), ParamType::OptionalBool(enabled)),
105 ("maximumFileSize".to_string(), ParamType::OptionalNumber(maximum_file_size)),
106 ("allowedFileExtensions".to_string(), ParamType::Array(allowed_file_extensions.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
107 ("encryption".to_string(), ParamType::OptionalBool(encryption)),
108 ("antivirus".to_string(), ParamType::OptionalBool(antivirus)),
109 ].iter().cloned().collect();
110
111 let response = self.client.clone().call("POST", &path, Some(headers), Some(params) );
112
113 let processedResponse:models::Bucket = match response {
114 Ok(r) => {
115 match r.json() {
116 Ok(json) => json,
117 Err(e) => {
118 return Err(AppwriteException::new(format!("Error parsing response json: {}", e), 0, "".to_string()));
119 }
120 }
121 }
122 Err(e) => {
123 return Err(e);
124 }
125 };
126
127 Ok(processedResponse)
128 }
129
130 pub fn get_bucket(&self, bucket_id: &str) -> Result<models::Bucket, AppwriteException> {
133 let path = "/storage/buckets/bucketId".replace("bucketId", &bucket_id);
134 let headers: HashMap<String, String> = [
135 ("content-type".to_string(), "application/json".to_string()),
136 ].iter().cloned().collect();
137
138 let params: HashMap<String, ParamType> = [
139 ].iter().cloned().collect();
140
141 let response = self.client.clone().call("GET", &path, Some(headers), Some(params) );
142
143 let processedResponse:models::Bucket = match response {
144 Ok(r) => {
145 match r.json() {
146 Ok(json) => json,
147 Err(e) => {
148 return Err(AppwriteException::new(format!("Error parsing response json: {}", e), 0, "".to_string()));
149 }
150 }
151 }
152 Err(e) => {
153 return Err(e);
154 }
155 };
156
157 Ok(processedResponse)
158 }
159
160 pub fn update_bucket(&self, bucket_id: &str, name: &str, permission: &str, read: Option<&[&str]>, write: Option<&[&str]>, enabled: Option<bool>, maximum_file_size: Option<i64>, allowed_file_extensions: Option<&[&str]>, encryption: Option<bool>, antivirus: Option<bool>) -> Result<models::Bucket, AppwriteException> {
162 let path = "/storage/buckets/bucketId".replace("bucketId", &bucket_id);
163 let headers: HashMap<String, String> = [
164 ("content-type".to_string(), "application/json".to_string()),
165 ].iter().cloned().collect();
166
167 let read:&[&str] = match read {
168 Some(data) => data,
169 None => &[]
170 };
171
172 let write:&[&str] = match write {
173 Some(data) => data,
174 None => &[]
175 };
176
177 let allowed_file_extensions:&[&str] = match allowed_file_extensions {
178 Some(data) => data,
179 None => &[]
180 };
181
182 let params: HashMap<String, ParamType> = [
183 ("name".to_string(), ParamType::String(name.to_string())),
184 ("permission".to_string(), ParamType::String(permission.to_string())),
185 ("read".to_string(), ParamType::Array(read.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
186 ("write".to_string(), ParamType::Array(write.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
187 ("enabled".to_string(), ParamType::OptionalBool(enabled)),
188 ("maximumFileSize".to_string(), ParamType::OptionalNumber(maximum_file_size)),
189 ("allowedFileExtensions".to_string(), ParamType::Array(allowed_file_extensions.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
190 ("encryption".to_string(), ParamType::OptionalBool(encryption)),
191 ("antivirus".to_string(), ParamType::OptionalBool(antivirus)),
192 ].iter().cloned().collect();
193
194 let response = self.client.clone().call("PUT", &path, Some(headers), Some(params) );
195
196 let processedResponse:models::Bucket = match response {
197 Ok(r) => {
198 match r.json() {
199 Ok(json) => json,
200 Err(e) => {
201 return Err(AppwriteException::new(format!("Error parsing response json: {}", e), 0, "".to_string()));
202 }
203 }
204 }
205 Err(e) => {
206 return Err(e);
207 }
208 };
209
210 Ok(processedResponse)
211 }
212
213 pub fn delete_bucket(&self, bucket_id: &str) -> Result<serde_json::value::Value, AppwriteException> {
215 let path = "/storage/buckets/bucketId".replace("bucketId", &bucket_id);
216 let headers: HashMap<String, String> = [
217 ("content-type".to_string(), "application/json".to_string()),
218 ].iter().cloned().collect();
219
220 let params: HashMap<String, ParamType> = [
221 ].iter().cloned().collect();
222
223 let response = self.client.clone().call("DELETE", &path, Some(headers), Some(params) );
224
225 match response {
226 Ok(r) => {
227 let status_code = r.status();
228 if status_code == reqwest::StatusCode::NO_CONTENT {
229 Ok(json!(true))
230 } else {
231 Ok(serde_json::from_str(&r.text().unwrap()).unwrap())
232 }
233 }
234 Err(e) => {
235 Err(e)
236 }
237 }
238 }
239
240 pub fn list_files(&self, bucket_id: &str, search: Option<&str>, limit: Option<i64>, offset: Option<i64>, cursor: Option<&str>, cursor_direction: Option<&str>, order_type: Option<&str>) -> Result<models::FileList, AppwriteException> {
244 let path = "/storage/buckets/bucketId/files".replace("bucketId", &bucket_id);
245 let headers: HashMap<String, String> = [
246 ("content-type".to_string(), "application/json".to_string()),
247 ].iter().cloned().collect();
248
249 let search:&str = match search {
250 Some(data) => data,
251 None => ""
252 };
253
254 let cursor:&str = match cursor {
255 Some(data) => data,
256 None => ""
257 };
258
259 let cursor_direction:&str = match cursor_direction {
260 Some(data) => data,
261 None => ""
262 };
263
264 let order_type:&str = match order_type {
265 Some(data) => data,
266 None => ""
267 };
268
269 let params: HashMap<String, ParamType> = [
270 ("search".to_string(), ParamType::String(search.to_string())),
271 ("limit".to_string(), ParamType::OptionalNumber(limit)),
272 ("offset".to_string(), ParamType::OptionalNumber(offset)),
273 ("cursor".to_string(), ParamType::String(cursor.to_string())),
274 ("cursorDirection".to_string(), ParamType::String(cursor_direction.to_string())),
275 ("orderType".to_string(), ParamType::String(order_type.to_string())),
276 ].iter().cloned().collect();
277
278 let response = self.client.clone().call("GET", &path, Some(headers), Some(params) );
279
280 let processedResponse:models::FileList = match response {
281 Ok(r) => {
282 match r.json() {
283 Ok(json) => json,
284 Err(e) => {
285 return Err(AppwriteException::new(format!("Error parsing response json: {}", e), 0, "".to_string()));
286 }
287 }
288 }
289 Err(e) => {
290 return Err(e);
291 }
292 };
293
294 Ok(processedResponse)
295 }
296
297 pub fn create_file(&self, bucket_id: &str, file_id: &str, file: std::path::PathBuf, read: Option<&[&str]>, write: Option<&[&str]>) -> Result<models::File, AppwriteException> {
316 let path = "/storage/buckets/bucketId/files".replace("bucketId", &bucket_id);
317 let mut headers: HashMap<String, String> = [
318 ("content-type".to_string(), "multipart/form-data".to_string()),
319 ].iter().cloned().collect();
320
321 let read:&[&str] = match read {
322 Some(data) => data,
323 None => &[]
324 };
325
326 let write:&[&str] = match write {
327 Some(data) => data,
328 None => &[]
329 };
330
331 let mut params: HashMap<String, ParamType> = [
332 ("fileId".to_string(), ParamType::String(file_id.to_string())),
333 ("read".to_string(), ParamType::Array(read.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
334 ("write".to_string(), ParamType::Array(write.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
335 ].iter().cloned().collect();
336
337 let mut fileBuf = std::fs::File::open(file.clone()).unwrap();
338
339 let size = fileBuf.metadata().unwrap().len();
340
341 match size {
342 size if size <= crate::client::CHUNK_SIZE => {
343 params.insert("file".to_string(), ParamType::FilePath(file));
344 match self.client.clone().call("POST", &path, Some(headers), Some(params)) {
345 Ok(r) => {
346 Ok(r.json::<models::File>().unwrap())
347 }
348 Err(e) => {
349 Err(e)
350 }
351 }
352 }
353 _ => {
354 let mut id = "".to_string();
356
357 let mut resumeCounter: u64 = 0;
358 let totalCounters = (((size / crate::client::CHUNK_SIZE) as f64).ceil() as u64) + 1;
359
360 if file_id != "unique()" {
361 let filePath = format!("/storage/buckets/bucketId/files{}", file_id);
362 match self.client.clone().call("GET", &filePath, Some(headers.clone()), None) {
363 Ok(r) => {
364 match r.json::<serde_json::Value>() {
365 Ok(data) => {
366 resumeCounter = data["chunksUploaded"].as_u64().unwrap();
367 },
368 Err(_e) => ()
369 };
370 }
371 Err(_e) => ()
372 };
373 }
374
375 let response: reqwest::blocking::Response;
376
377 for counter in resumeCounter..totalCounters {
378 let mut headers: HashMap<String, String> = [
379 ("content-type".to_string(), "multipart/form-data".to_string()),
380 ].iter().cloned().collect();
381
382 let mut params = params.clone();
383
384 headers.insert("content-range".to_string(), format!("bytes {}-{}/{}", (counter * crate::client::CHUNK_SIZE),
385 std::cmp::min((counter * crate::client::CHUNK_SIZE) + crate::client::CHUNK_SIZE - 1, size), size));
386
387 if id.len() != 0 {
388 headers.insert("x-appwrite-id".to_string(), id.to_string());
389 }
390
391 let mut chunk = Vec::with_capacity(crate::client::CHUNK_SIZE as usize);
392
393 match fileBuf.by_ref().take(crate::client::CHUNK_SIZE).read_to_end(&mut chunk) {
394 Ok(_) => (),
395 Err(e) => {
396 return Err(AppwriteException::new(format!("A error occoured. ERR: {}, This could either be a connection error or an internal Appwrite error. Please check your Appwrite instance logs. ", e), 0, "".to_string()))
397 }
398 };
399
400 params.insert("file".to_string(), ParamType::StreamData(chunk, file.file_name().unwrap().to_string_lossy().to_string()));
401
402 let response = match self.client.clone().call("POST", &path, Some(headers), Some(params)) {
403 Ok(r) => r,
404 Err(e) => {
405 return Err(e);
406 }
407 };
408
409 if counter == totalCounters - 1 {
411 return Ok(response.json::<models::File>().unwrap());
412 } else {
413 if id.len() == 0 {
414 id = response.json::<serde_json::Value>().unwrap()["$id"].as_str().unwrap().to_owned();
415 }
416 }
417 };
418
419 return Err(AppwriteException::new("Error uploading chunk data.".to_string(), 500, "0".to_string()));
420 }
421 }
422 }
423
424 pub fn get_file(&self, bucket_id: &str, file_id: &str) -> Result<models::File, AppwriteException> {
427 let path = "/storage/buckets/bucketId/files/fileId".replace("bucketId", &bucket_id).replace("fileId", &file_id);
428 let headers: HashMap<String, String> = [
429 ("content-type".to_string(), "application/json".to_string()),
430 ].iter().cloned().collect();
431
432 let params: HashMap<String, ParamType> = [
433 ].iter().cloned().collect();
434
435 let response = self.client.clone().call("GET", &path, Some(headers), Some(params) );
436
437 let processedResponse:models::File = match response {
438 Ok(r) => {
439 match r.json() {
440 Ok(json) => json,
441 Err(e) => {
442 return Err(AppwriteException::new(format!("Error parsing response json: {}", e), 0, "".to_string()));
443 }
444 }
445 }
446 Err(e) => {
447 return Err(e);
448 }
449 };
450
451 Ok(processedResponse)
452 }
453
454 pub fn update_file(&self, bucket_id: &str, file_id: &str, read: Option<&[&str]>, write: Option<&[&str]>) -> Result<models::File, AppwriteException> {
457 let path = "/storage/buckets/bucketId/files/fileId".replace("bucketId", &bucket_id).replace("fileId", &file_id);
458 let headers: HashMap<String, String> = [
459 ("content-type".to_string(), "application/json".to_string()),
460 ].iter().cloned().collect();
461
462 let read:&[&str] = match read {
463 Some(data) => data,
464 None => &[]
465 };
466
467 let write:&[&str] = match write {
468 Some(data) => data,
469 None => &[]
470 };
471
472 let params: HashMap<String, ParamType> = [
473 ("read".to_string(), ParamType::Array(read.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
474 ("write".to_string(), ParamType::Array(write.into_iter().map(|x| ParamType::String(x.to_string())).collect())),
475 ].iter().cloned().collect();
476
477 let response = self.client.clone().call("PUT", &path, Some(headers), Some(params) );
478
479 let processedResponse:models::File = match response {
480 Ok(r) => {
481 match r.json() {
482 Ok(json) => json,
483 Err(e) => {
484 return Err(AppwriteException::new(format!("Error parsing response json: {}", e), 0, "".to_string()));
485 }
486 }
487 }
488 Err(e) => {
489 return Err(e);
490 }
491 };
492
493 Ok(processedResponse)
494 }
495
496 pub fn delete_file(&self, bucket_id: &str, file_id: &str) -> Result<serde_json::value::Value, AppwriteException> {
499 let path = "/storage/buckets/bucketId/files/fileId".replace("bucketId", &bucket_id).replace("fileId", &file_id);
500 let headers: HashMap<String, String> = [
501 ("content-type".to_string(), "application/json".to_string()),
502 ].iter().cloned().collect();
503
504 let params: HashMap<String, ParamType> = [
505 ].iter().cloned().collect();
506
507 let response = self.client.clone().call("DELETE", &path, Some(headers), Some(params) );
508
509 match response {
510 Ok(r) => {
511 let status_code = r.status();
512 if status_code == reqwest::StatusCode::NO_CONTENT {
513 Ok(json!(true))
514 } else {
515 Ok(serde_json::from_str(&r.text().unwrap()).unwrap())
516 }
517 }
518 Err(e) => {
519 Err(e)
520 }
521 }
522 }
523
524 pub fn get_file_download(&self, bucket_id: &str, file_id: &str) -> Result<Vec<u8>, AppwriteException> {
528 let path = "/storage/buckets/bucketId/files/fileId/download".replace("bucketId", &bucket_id).replace("fileId", &file_id);
529 let headers: HashMap<String, String> = [
530 ("content-type".to_string(), "application/json".to_string()),
531 ].iter().cloned().collect();
532
533 let params: HashMap<String, ParamType> = [
534 ].iter().cloned().collect();
535
536 let response = self.client.clone().call("GET", &path, Some(headers), Some(params) );
537
538 let processedResponse:Vec<u8> = match response {
539 Ok(mut r) => {
540 let mut buf: Vec<u8> = vec![];
541 match r.copy_to(&mut buf) {
542 Ok(_) => (),
543 Err(e) => {
544 return Err(AppwriteException::new(format!("Error copying response to buffer: {}", e), 0, "".to_string()));
545 }
546 };
547 buf
548 }
549 Err(e) => {
550 return Err(e);
551 }
552 };
553
554 Ok(processedResponse)
555 }
556
557 pub fn get_file_preview(&self, bucket_id: &str, file_id: &str, width: Option<i64>, height: Option<i64>, gravity: Option<&str>, quality: Option<i64>, border_width: Option<i64>, border_color: Option<&str>, border_radius: Option<i64>, opacity: Option<f64>, rotation: Option<i64>, background: Option<&str>, output: Option<&str>) -> Result<Vec<u8>, AppwriteException> {
563 let path = "/storage/buckets/bucketId/files/fileId/preview".replace("bucketId", &bucket_id).replace("fileId", &file_id);
564 let headers: HashMap<String, String> = [
565 ("content-type".to_string(), "application/json".to_string()),
566 ].iter().cloned().collect();
567
568 let gravity:&str = match gravity {
569 Some(data) => data,
570 None => ""
571 };
572
573 let border_color:&str = match border_color {
574 Some(data) => data,
575 None => ""
576 };
577
578 let background:&str = match background {
579 Some(data) => data,
580 None => ""
581 };
582
583 let output:&str = match output {
584 Some(data) => data,
585 None => ""
586 };
587
588 let params: HashMap<String, ParamType> = [
589 ("width".to_string(), ParamType::OptionalNumber(width)),
590 ("height".to_string(), ParamType::OptionalNumber(height)),
591 ("gravity".to_string(), ParamType::String(gravity.to_string())),
592 ("quality".to_string(), ParamType::OptionalNumber(quality)),
593 ("borderWidth".to_string(), ParamType::OptionalNumber(border_width)),
594 ("borderColor".to_string(), ParamType::String(border_color.to_string())),
595 ("borderRadius".to_string(), ParamType::OptionalNumber(border_radius)),
596 ("opacity".to_string(), ParamType::OptionalFloat(opacity)),
597 ("rotation".to_string(), ParamType::OptionalNumber(rotation)),
598 ("background".to_string(), ParamType::String(background.to_string())),
599 ("output".to_string(), ParamType::String(output.to_string())),
600 ].iter().cloned().collect();
601
602 let response = self.client.clone().call("GET", &path, Some(headers), Some(params) );
603
604 let processedResponse:Vec<u8> = match response {
605 Ok(mut r) => {
606 let mut buf: Vec<u8> = vec![];
607 match r.copy_to(&mut buf) {
608 Ok(_) => (),
609 Err(e) => {
610 return Err(AppwriteException::new(format!("Error copying response to buffer: {}", e), 0, "".to_string()));
611 }
612 };
613 buf
614 }
615 Err(e) => {
616 return Err(e);
617 }
618 };
619
620 Ok(processedResponse)
621 }
622
623 pub fn get_file_view(&self, bucket_id: &str, file_id: &str) -> Result<Vec<u8>, AppwriteException> {
627 let path = "/storage/buckets/bucketId/files/fileId/view".replace("bucketId", &bucket_id).replace("fileId", &file_id);
628 let headers: HashMap<String, String> = [
629 ("content-type".to_string(), "application/json".to_string()),
630 ].iter().cloned().collect();
631
632 let params: HashMap<String, ParamType> = [
633 ].iter().cloned().collect();
634
635 let response = self.client.clone().call("GET", &path, Some(headers), Some(params) );
636
637 let processedResponse:Vec<u8> = match response {
638 Ok(mut r) => {
639 let mut buf: Vec<u8> = vec![];
640 match r.copy_to(&mut buf) {
641 Ok(_) => (),
642 Err(e) => {
643 return Err(AppwriteException::new(format!("Error copying response to buffer: {}", e), 0, "".to_string()));
644 }
645 };
646 buf
647 }
648 Err(e) => {
649 return Err(e);
650 }
651 };
652
653 Ok(processedResponse)
654 }
655
656 pub fn get_usage(&self, range: Option<&str>) -> Result<models::UsageStorage, AppwriteException> {
657 let path = "/storage/usage";
658 let headers: HashMap<String, String> = [
659 ("content-type".to_string(), "application/json".to_string()),
660 ].iter().cloned().collect();
661
662 let range:&str = match range {
663 Some(data) => data,
664 None => ""
665 };
666
667 let params: HashMap<String, ParamType> = [
668 ("range".to_string(), ParamType::String(range.to_string())),
669 ].iter().cloned().collect();
670
671 let response = self.client.clone().call("GET", &path, Some(headers), Some(params) );
672
673 let processedResponse:models::UsageStorage = match response {
674 Ok(r) => {
675 match r.json() {
676 Ok(json) => json,
677 Err(e) => {
678 return Err(AppwriteException::new(format!("Error parsing response json: {}", e), 0, "".to_string()));
679 }
680 }
681 }
682 Err(e) => {
683 return Err(e);
684 }
685 };
686
687 Ok(processedResponse)
688 }
689
690 pub fn get_bucket_usage(&self, bucket_id: &str, range: Option<&str>) -> Result<models::UsageBuckets, AppwriteException> {
691 let path = "/storage/bucketId/usage".replace("bucketId", &bucket_id);
692 let headers: HashMap<String, String> = [
693 ("content-type".to_string(), "application/json".to_string()),
694 ].iter().cloned().collect();
695
696 let range:&str = match range {
697 Some(data) => data,
698 None => ""
699 };
700
701 let params: HashMap<String, ParamType> = [
702 ("range".to_string(), ParamType::String(range.to_string())),
703 ].iter().cloned().collect();
704
705 let response = self.client.clone().call("GET", &path, Some(headers), Some(params) );
706
707 let processedResponse:models::UsageBuckets = match response {
708 Ok(r) => {
709 match r.json() {
710 Ok(json) => json,
711 Err(e) => {
712 return Err(AppwriteException::new(format!("Error parsing response json: {}", e), 0, "".to_string()));
713 }
714 }
715 }
716 Err(e) => {
717 return Err(e);
718 }
719 };
720
721 Ok(processedResponse)
722 }
723}