opendal/services/ipmfs/
core.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18use std::fmt::Debug;
19use std::fmt::Formatter;
20use std::fmt::Write;
21use std::sync::Arc;
22
23use http::Request;
24use http::Response;
25
26use crate::raw::*;
27use crate::*;
28
29pub struct IpmfsCore {
30    pub info: Arc<AccessorInfo>,
31    pub root: String,
32    pub endpoint: String,
33}
34
35impl Debug for IpmfsCore {
36    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
37        f.debug_struct("IpmfsCore")
38            .field("root", &self.root)
39            .field("endpoint", &self.endpoint)
40            .finish()
41    }
42}
43
44impl IpmfsCore {
45    pub async fn ipmfs_stat(&self, path: &str) -> Result<Response<Buffer>> {
46        let p = build_rooted_abs_path(&self.root, path);
47
48        let url = format!(
49            "{}/api/v0/files/stat?arg={}",
50            self.endpoint,
51            percent_encode_path(&p)
52        );
53
54        let req = Request::post(url);
55        let req = req.body(Buffer::new()).map_err(new_request_build_error)?;
56
57        self.info.http_client().send(req).await
58    }
59
60    pub async fn ipmfs_read(&self, path: &str, range: BytesRange) -> Result<Response<HttpBody>> {
61        let p = build_rooted_abs_path(&self.root, path);
62
63        let mut url = format!(
64            "{}/api/v0/files/read?arg={}",
65            self.endpoint,
66            percent_encode_path(&p)
67        );
68
69        write!(url, "&offset={}", range.offset()).expect("write into string must succeed");
70        if let Some(count) = range.size() {
71            write!(url, "&count={count}").expect("write into string must succeed")
72        }
73
74        let req = Request::post(url);
75        let req = req.body(Buffer::new()).map_err(new_request_build_error)?;
76
77        self.info.http_client().fetch(req).await
78    }
79
80    pub async fn ipmfs_rm(&self, path: &str) -> Result<Response<Buffer>> {
81        let p = build_rooted_abs_path(&self.root, path);
82
83        let url = format!(
84            "{}/api/v0/files/rm?arg={}",
85            self.endpoint,
86            percent_encode_path(&p)
87        );
88
89        let req = Request::post(url);
90        let req = req.body(Buffer::new()).map_err(new_request_build_error)?;
91
92        self.info.http_client().send(req).await
93    }
94
95    pub(crate) async fn ipmfs_ls(&self, path: &str) -> Result<Response<Buffer>> {
96        let p = build_rooted_abs_path(&self.root, path);
97
98        let url = format!(
99            "{}/api/v0/files/ls?arg={}&long=true",
100            self.endpoint,
101            percent_encode_path(&p)
102        );
103
104        let req = Request::post(url);
105        let req = req.body(Buffer::new()).map_err(new_request_build_error)?;
106
107        self.info.http_client().send(req).await
108    }
109
110    pub async fn ipmfs_mkdir(&self, path: &str) -> Result<Response<Buffer>> {
111        let p = build_rooted_abs_path(&self.root, path);
112
113        let url = format!(
114            "{}/api/v0/files/mkdir?arg={}&parents=true",
115            self.endpoint,
116            percent_encode_path(&p)
117        );
118
119        let req = Request::post(url);
120        let req = req.body(Buffer::new()).map_err(new_request_build_error)?;
121
122        self.info.http_client().send(req).await
123    }
124
125    /// Support write from reader.
126    pub async fn ipmfs_write(&self, path: &str, body: Buffer) -> Result<Response<Buffer>> {
127        let p = build_rooted_abs_path(&self.root, path);
128
129        let url = format!(
130            "{}/api/v0/files/write?arg={}&parents=true&create=true&truncate=true",
131            self.endpoint,
132            percent_encode_path(&p)
133        );
134
135        let multipart = Multipart::new().part(FormDataPart::new("data").content(body));
136
137        let req: http::request::Builder = Request::post(url);
138        let req = multipart.apply(req)?;
139
140        self.info.http_client().send(req).await
141    }
142}