cyfs_lib/util/
requestor.rs

1use super::request::*;
2use super::processor::*;
3use crate::{base::*, requestor::*, SharedObjectStackDecID, UtilBuildDirFromObjectMapOutputRequest, UtilBuildDirFromObjectMapOutputResponse, UtilBuildFileOutputRequest, UtilBuildFileOutputResponse};
4use cyfs_base::*;
5
6use cyfs_core::{Zone, ZoneId};
7use http_types::{Method, Request, Response, Url};
8use std::sync::Arc;
9
10#[derive(Clone)]
11pub struct UtilRequestor {
12    dec_id: Option<SharedObjectStackDecID>,
13    requestor: HttpRequestorRef,
14    service_url: Url,
15}
16
17impl UtilRequestor {
18    pub fn new(dec_id: Option<SharedObjectStackDecID>, requestor: HttpRequestorRef) -> Self {
19        let addr = requestor.remote_addr();
20
21        let url = format!("http://{}/util/", addr);
22        let url = Url::parse(&url).unwrap();
23
24        Self {
25            dec_id,
26            requestor,
27            service_url: url,
28        }
29    }
30
31    pub fn into_processor(self) -> UtilOutputProcessorRef {
32        Arc::new(Box::new(self))
33    }
34
35    pub fn clone_processor(&self) -> UtilOutputProcessorRef {
36        self.clone().into_processor()
37    }
38
39    fn encode_common_headers(&self, com_req: &UtilRequestCommon, http_req: &mut Request) {
40        if let Some(dec_id) = &com_req.dec_id {
41            http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string());
42        } else if let Some(dec_id) = &self.dec_id {
43            if let Some(dec_id) = dec_id.get() {
44                http_req.insert_header(cyfs_base::CYFS_DEC_ID, dec_id.to_string());
45            }
46        }
47
48        RequestorHelper::encode_opt_header_with_encoding(http_req, cyfs_base::CYFS_REQ_PATH, com_req.req_path.as_deref());
49
50        if let Some(target) = &com_req.target {
51            http_req.insert_header(cyfs_base::CYFS_TARGET, target.to_string());
52        }
53
54        http_req.insert_header(cyfs_base::CYFS_FLAGS, com_req.flags.to_string());
55    }
56
57    fn encode_get_device_request(&self, req: &UtilGetDeviceRequest) -> Request {
58        let url = self.service_url.join("device").unwrap();
59        let mut http_req = Request::new(Method::Get, url);
60        self.encode_common_headers(&req.common, &mut http_req);
61
62        http_req
63    }
64
65    async fn decode_get_device_response(
66        mut resp: Response,
67    ) -> BuckyResult<UtilGetDeviceResponse> {
68        let buf = resp.body_bytes().await.map_err(|e| {
69            let msg = format!("get_current_device failed, read body bytes error! {}", e);
70            error!("{}", msg);
71
72            BuckyError::from(msg)
73        })?;
74
75        let (device, _) = Device::raw_decode(&buf).map_err(|e| {
76            error!("decode device from resp bytes error: {}", e);
77            e
78        })?;
79
80        let device_id: DeviceId = device.desc().device_id().clone();
81
82        Ok(UtilGetDeviceResponse { device_id, device })
83    }
84
85    // xxx/util/device
86    pub async fn get_device(
87        &self,
88        req: UtilGetDeviceRequest,
89    ) -> BuckyResult<UtilGetDeviceResponse> {
90        let http_req = self.encode_get_device_request(&req);
91
92        let mut resp = self.requestor.request(http_req).await?;
93
94        if resp.status().is_success() {
95            let resp = Self::decode_get_device_response(resp).await?;
96            info!("util get_device from non stack success: {}", resp);
97
98            Ok(resp)
99        } else {
100            let e = RequestorHelper::error_from_resp(&mut resp).await;
101            Err(e)
102        }
103    }
104
105    fn encode_get_zone_request(&self, req: UtilGetZoneRequest) -> Request {
106        let url = self.service_url.join("zone").unwrap();
107        let mut http_req = Request::new(Method::Post, url);
108        self.encode_common_headers(&req.common, &mut http_req);
109
110        RequestorHelper::encode_opt_header(&mut http_req, cyfs_base::CYFS_OBJECT_ID, &req.object_id);
111        if let Some(object_raw) = req.object_raw {
112            http_req.set_body(object_raw);
113        }
114
115        http_req
116    }
117    async fn decode_get_zone_response(
118        mut resp: Response,
119    ) -> BuckyResult<UtilGetZoneResponse> {
120        let zone: Zone = RequestorHelper::decode_raw_object_body(&mut resp).await?;
121        let zone_id: ZoneId = RequestorHelper::decode_header(&resp, cyfs_base::CYFS_ZONE_ID)?;
122
123        let device_id = RequestorHelper::decode_header(&resp, cyfs_base::CYFS_OOD_DEVICE_ID)?;
124
125        let resp = UtilGetZoneResponse {
126            zone,
127            zone_id,
128            device_id,
129        };
130
131        info!("util get_zone from non stack success: {}", resp);
132
133        Ok(resp)
134    }
135
136    // 根据device/people/simplegroup查询所在的zone
137    // 如果已知object的内容,那么可以附带,加速non-stack的查询
138    // xxx/util/zone[/object_id]
139    pub async fn get_zone(
140        &self,
141        req: UtilGetZoneRequest,
142    ) -> BuckyResult<UtilGetZoneResponse> {
143        let http_req = self.encode_get_zone_request(req);
144
145        let mut resp = self.requestor.request(http_req).await?;
146
147        if resp.status().is_success() {
148            let resp = Self::decode_get_zone_response(resp).await?;
149
150            Ok(resp)
151        } else {
152            let e = RequestorHelper::error_from_resp(&mut resp).await;
153            Err(e)
154        }
155    }
156
157    fn encode_resolve_ood_request(&self, req: &UtilResolveOODRequest) -> Request {
158        let url = self.service_url.join("resolve_ood").unwrap();
159
160        // 目前没有body
161        let mut http_req = Request::new(Method::Get, url);
162        RequestorHelper::encode_header(&mut http_req, cyfs_base::CYFS_OBJECT_ID, &req.object_id);
163        RequestorHelper::encode_opt_header(&mut http_req, cyfs_base::CYFS_OWNER_ID, &req.owner_id);
164
165        self.encode_common_headers(&req.common, &mut http_req);
166
167        http_req
168    }
169
170    pub async fn resolve_ood(
171        &self,
172        req: UtilResolveOODRequest,
173    ) -> BuckyResult<UtilResolveOODResponse> {
174        let http_req = self.encode_resolve_ood_request(&req);
175        let mut resp = self.requestor.request(http_req).await?;
176
177        if resp.status().is_success() {
178            let resp = RequestorHelper::decode_json_body(&mut resp).await?;
179            Ok(resp)
180        } else {
181            let e = RequestorHelper::error_from_resp(&mut resp).await;
182            Err(e)
183        }
184    }
185
186    fn encode_get_ood_status_request(&self, req: UtilGetOODStatusRequest) -> Request {
187        let url = self.service_url.join("ood_status").unwrap();
188        let mut http_req = Request::new(Method::Get, url);
189        self.encode_common_headers(&req.common, &mut http_req);
190
191        http_req
192    }
193
194    pub async fn get_ood_status(
195        &self,
196        req: UtilGetOODStatusRequest,
197    ) -> BuckyResult<UtilGetOODStatusResponse> {
198        let http_req = self.encode_get_ood_status_request(req);
199
200        let mut resp = self.requestor.request(http_req).await?;
201
202        if resp.status().is_success() {
203            let resp = resp.body_json().await.map_err(|e| {
204                let msg = format!("parse get_ood_status resp body error! err={}", e);
205                error!("{}", msg);
206                BuckyError::new(BuckyErrorCode::InvalidData, msg)
207            })?;
208
209            Ok(resp)
210        } else {
211            let e = RequestorHelper::error_from_resp(&mut resp).await;
212            error!(
213                "util get_ood_status failed: status={}, {}",
214                resp.status(),
215                e
216            );
217
218            Err(e)
219        }
220    }
221
222    fn encode_get_noc_info_request(&self, req: UtilGetNOCInfoRequest) -> Request {
223        let url = self.service_url.join("noc_info").unwrap();
224        let mut http_req = Request::new(Method::Get, url);
225        self.encode_common_headers(&req.common, &mut http_req);
226
227        http_req
228    }
229
230    pub async fn get_noc_info(
231        &self,
232        req: UtilGetNOCInfoRequest,
233    ) -> BuckyResult<UtilGetNOCInfoResponse> {
234        let http_req = self.encode_get_noc_info_request(req);
235
236        let mut resp = self.requestor.request(http_req).await?;
237
238        if resp.status().is_success() {
239            let resp = resp.body_json().await.map_err(|e| {
240                let msg = format!("parse get_noc_stat resp body error! err={}", e);
241                error!("{}", msg);
242                BuckyError::new(BuckyErrorCode::InvalidData, msg)
243            })?;
244
245            Ok(resp)
246        } else {
247            let e = RequestorHelper::error_from_resp(&mut resp).await;
248            error!("util get_noc_stat failed: status={}, {}", resp.status(), e);
249
250            Err(e)
251        }
252    }
253
254    fn encode_get_network_access_info_request(
255        &self,
256        req: UtilGetNetworkAccessInfoRequest,
257    ) -> Request {
258        let url = self.service_url.join("network_access_info").unwrap();
259        let mut http_req = Request::new(Method::Get, url);
260        self.encode_common_headers(&req.common, &mut http_req);
261
262        http_req
263    }
264
265    pub async fn get_network_access_info(
266        &self,
267        req: UtilGetNetworkAccessInfoRequest,
268    ) -> BuckyResult<UtilGetNetworkAccessInfoResponse> {
269        let http_req = self.encode_get_network_access_info_request(req);
270
271        let mut resp = self.requestor.request(http_req).await?;
272
273        if resp.status().is_success() {
274            let resp = RequestorHelper::decode_json_body(&mut resp)
275                .await
276                .map_err(|e| {
277                    let msg = format!("parse get_network_access_info resp body error! err={}", e);
278                    error!("{}", msg);
279                    BuckyError::new(BuckyErrorCode::InvalidData, msg)
280                })?;
281
282            Ok(resp)
283        } else {
284            let e = RequestorHelper::error_from_resp(&mut resp).await;
285            error!(
286                "util get_network_access_info failed: status={}, {}",
287                resp.status(),
288                e
289            );
290
291            Err(e)
292        }
293    }
294
295    fn encode_get_device_static_info_request(
296        &self,
297        req: UtilGetDeviceStaticInfoRequest,
298    ) -> Request {
299        let url = self.service_url.join("device_static_info").unwrap();
300        let mut http_req = Request::new(Method::Get, url);
301        self.encode_common_headers(&req.common, &mut http_req);
302
303        http_req
304    }
305
306    pub async fn get_device_static_info(
307        &self,
308        req: UtilGetDeviceStaticInfoRequest,
309    ) -> BuckyResult<UtilGetDeviceStaticInfoResponse> {
310        let http_req = self.encode_get_device_static_info_request(req);
311
312        let mut resp = self.requestor.request(http_req).await?;
313
314        if resp.status().is_success() {
315            let content = RequestorHelper::decode_json_body(&mut resp)
316                .await
317                .map_err(|e| {
318                    let msg = format!("parse get_device_static_info resp body error! err={}", e);
319                    error!("{}", msg);
320                    BuckyError::new(BuckyErrorCode::InvalidData, msg)
321                })?;
322
323            Ok(content)
324        } else {
325            let e = RequestorHelper::error_from_resp(&mut resp).await;
326            error!(
327                "util get_device_static_info failed: status={}, {}",
328                resp.status(),
329                e
330            );
331
332            Err(e)
333        }
334    }
335
336    fn encode_get_system_info_request(&self, req: UtilGetSystemInfoRequest) -> Request {
337        let url = self.service_url.join("system_info").unwrap();
338        let mut http_req = Request::new(Method::Get, url);
339        self.encode_common_headers(&req.common, &mut http_req);
340
341        http_req
342    }
343
344    pub async fn get_system_info(
345        &self,
346        req: UtilGetSystemInfoRequest,
347    ) -> BuckyResult<UtilGetSystemInfoResponse> {
348        let http_req = self.encode_get_system_info_request(req);
349
350        let mut resp = self.requestor.request(http_req).await?;
351
352        if resp.status().is_success() {
353            let content = resp.body_json().await.map_err(|e| {
354                let msg = format!("parse get_system_info resp body error! err={}", e);
355                error!("{}", msg);
356                BuckyError::new(BuckyErrorCode::InvalidData, msg)
357            })?;
358
359            Ok(content)
360        } else {
361            let e = RequestorHelper::error_from_resp(&mut resp).await;
362            error!(
363                "util get_system_info failed: status={}, {}",
364                resp.status(),
365                e
366            );
367
368            Err(e)
369        }
370    }
371
372    fn encode_get_version_info_request(&self, req: UtilGetVersionInfoRequest) -> Request {
373        let url = self.service_url.join("version_info").unwrap();
374        let mut http_req = Request::new(Method::Get, url);
375        self.encode_common_headers(&req.common, &mut http_req);
376
377        http_req
378    }
379
380    pub async fn get_version_info(
381        &self,
382        req: UtilGetVersionInfoRequest,
383    ) -> BuckyResult<UtilGetVersionInfoResponse> {
384        let http_req = self.encode_get_version_info_request(req);
385
386        let mut resp = self.requestor.request(http_req).await?;
387
388        if resp.status().is_success() {
389            let content = RequestorHelper::decode_json_body(&mut resp)
390                .await
391                .map_err(|e| {
392                    let msg = format!("parse get_version_info resp body error! err={}", e);
393                    error!("{}", msg);
394                    BuckyError::new(BuckyErrorCode::InvalidData, msg)
395                })?;
396
397            Ok(content)
398        } else {
399            let e = RequestorHelper::error_from_resp(&mut resp).await;
400            error!(
401                "util get_version_info failed: status={}, {}",
402                resp.status(),
403                e
404            );
405
406            Err(e)
407        }
408    }
409
410    pub async fn build_file_object(
411        &self,
412        req: UtilBuildFileOutputRequest
413    ) -> BuckyResult<UtilBuildFileOutputResponse> {
414        let url = self.service_url.join("build_file").unwrap();
415        let mut http_req = Request::new(Method::Post, url);
416        self.encode_common_headers(&req.common, &mut http_req);
417        let body = req.encode_string();
418        http_req.set_body(body);
419
420        let mut resp = self.requestor.request(http_req).await?;
421        if resp.status().is_success() {
422            let content = RequestorHelper::decode_json_body(&mut resp)
423                .await
424                .map_err(|e| {
425                    let msg = format!("parse build file resp body error! err={}", e);
426                    error!("{}", msg);
427                    BuckyError::new(BuckyErrorCode::InvalidData, msg)
428                })?;
429
430            Ok(content)
431        } else {
432            let e = RequestorHelper::error_from_resp(&mut resp).await;
433            error!(
434                "util build_file_object failed: status={}, {}",
435                resp.status(),
436                e
437            );
438
439            Err(e)
440        }
441    }
442
443    pub async fn build_dir_from_object_map(
444        &self,
445        req: UtilBuildDirFromObjectMapOutputRequest
446    ) -> BuckyResult<UtilBuildDirFromObjectMapOutputResponse> {
447        let url = self.service_url.join("build_dir_from_object_map").unwrap();
448        let mut http_req = Request::new(Method::Post, url);
449        self.encode_common_headers(&req.common, &mut http_req);
450        let body = req.encode_string();
451        http_req.set_body(body);
452
453        let mut resp = self.requestor.request(http_req).await?;
454        if resp.status().is_success() {
455            let content = RequestorHelper::decode_json_body(&mut resp)
456                .await
457                .map_err(|e| {
458                    let msg = format!("parse build dir resp body error! err={}", e);
459                    error!("{}", msg);
460                    BuckyError::new(BuckyErrorCode::InvalidData, msg)
461                })?;
462
463            Ok(content)
464        } else {
465            let e = RequestorHelper::error_from_resp(&mut resp).await;
466            error!(
467                "util build_dir_from_object_map failed: status={}, {}",
468                resp.status(),
469                e
470            );
471
472            Err(e)
473        }
474    }
475}
476
477#[async_trait::async_trait]
478impl UtilOutputProcessor for UtilRequestor {
479    async fn get_device(
480        &self,
481        req: UtilGetDeviceRequest,
482    ) -> BuckyResult<UtilGetDeviceResponse> {
483        Self::get_device(&self, req).await
484    }
485
486    async fn get_zone(
487        &self,
488        req: UtilGetZoneRequest,
489    ) -> BuckyResult<UtilGetZoneResponse> {
490        Self::get_zone(&self, req).await
491    }
492
493    async fn resolve_ood(
494        &self,
495        req: UtilResolveOODRequest,
496    ) -> BuckyResult<UtilResolveOODResponse> {
497        Self::resolve_ood(&self, req).await
498    }
499
500    async fn get_ood_status(
501        &self,
502        req: UtilGetOODStatusRequest,
503    ) -> BuckyResult<UtilGetOODStatusResponse> {
504        Self::get_ood_status(&self, req).await
505    }
506
507    async fn get_noc_info(
508        &self,
509        req: UtilGetNOCInfoRequest,
510    ) -> BuckyResult<UtilGetNOCInfoResponse> {
511        Self::get_noc_info(&self, req).await
512    }
513
514    async fn get_network_access_info(
515        &self,
516        req: UtilGetNetworkAccessInfoRequest,
517    ) -> BuckyResult<UtilGetNetworkAccessInfoResponse> {
518        Self::get_network_access_info(&self, req).await
519    }
520
521    async fn get_device_static_info(
522        &self,
523        req: UtilGetDeviceStaticInfoRequest,
524    ) -> BuckyResult<UtilGetDeviceStaticInfoResponse> {
525        Self::get_device_static_info(&self, req).await
526    }
527
528    async fn get_system_info(
529        &self,
530        req: UtilGetSystemInfoRequest,
531    ) -> BuckyResult<UtilGetSystemInfoResponse> {
532        Self::get_system_info(&self, req).await
533    }
534
535    async fn get_version_info(
536        &self,
537        req: UtilGetVersionInfoRequest,
538    ) -> BuckyResult<UtilGetVersionInfoResponse> {
539        Self::get_version_info(&self, req).await
540    }
541
542    async fn build_file_object(&self, req: UtilBuildFileOutputRequest) -> BuckyResult<UtilBuildFileOutputResponse> {
543        Self::build_file_object(self, req).await
544    }
545
546    async fn build_dir_from_object_map(&self, req: UtilBuildDirFromObjectMapOutputRequest)
547        -> BuckyResult<UtilBuildDirFromObjectMapOutputResponse> {
548        Self::build_dir_from_object_map(self, req).await
549    }
550}