supabase_storage/build/object/sign.rs
1use reqwest::{header::HeaderValue, Method};
2
3use crate::build::{
4 builder::{BodyType, Builder},
5 executor::Executor,
6};
7
8impl Builder {
9 /// generate presigned url to retrieve an object
10 ///
11 /// # Arguments
12 ///
13 /// * `bucket_name` - bucket name
14 /// * `object` - object name
15 ///
16 /// # Returns
17 ///
18 /// * `Executor` - The constructed `Executor` instance for executing the request.
19 ///
20 /// # Example
21 /// ```
22 /// use supabase_storage::{
23 /// Storage,
24 /// config::SupabaseConfig,
25 /// model::bucket::NewBucket,
26 /// };
27 /// use dotenv::dotenv;
28 ///
29 /// #[tokio::main]
30 /// async fn main() {
31 /// dotenv().ok();
32 /// let config = SupabaseConfig::default();
33 /// let response = Storage::new_with_config(config)
34 /// .from()
35 /// .create_signed_url("thefux", "bitcoin.pdf", r#"
36 /// {
37 /// "expiresIn": 3600,
38 /// "transform": {
39 /// "height": 0,
40 /// "width": 0,
41 /// "resize": "cover",
42 /// "format": "origin",
43 /// "quality": 100
44 /// }
45 /// }"#)
46 /// .execute()
47 /// .await
48 /// .unwrap();
49 /// }
50 /// ```
51 pub fn create_signed_url(mut self, bucket_name: &str, object: &str, body: &str) -> Executor {
52 self.headers
53 .insert("Content-Type", HeaderValue::from_static("application/json"));
54 self.method = Method::POST;
55 self.url
56 .path_segments_mut()
57 .unwrap()
58 .push("object")
59 .push("sign")
60 .push(bucket_name)
61 .push(object);
62
63 self.body = Some(BodyType::StringBody(body.to_string()));
64 self.create_executor()
65 }
66
67 /// generate presigned urls to retrieve objects
68 ///
69 /// # Arguments
70 ///
71 /// * `bucket_name` - bucket name
72 /// * `object` - object name
73 ///
74 /// # Returns
75 ///
76 /// * `Executor` - The constructed `Executor` instance for executing the request.
77 ///
78 /// # Example
79 /// ```
80 /// use supabase_storage::{
81 /// Storage,
82 /// config::SupabaseConfig,
83 /// model::bucket::NewBucket,
84 /// };
85 /// use dotenv::dotenv;
86 ///
87 /// #[tokio::main]
88 /// async fn main() {
89 /// dotenv().ok();
90 /// let config = SupabaseConfig::default();
91 /// let response = Storage::new_with_config(config)
92 /// .from()
93 /// .create_signed_urls("thefux", r#"{"expiresIn": 3600, "paths": ["hello.pdf", "test.pdf"]}"#)
94 /// .execute()
95 /// .await
96 /// .unwrap();
97 /// }
98 /// ```
99 pub fn create_signed_urls(mut self, bucket_name: &str, body: &str) -> Executor {
100 self.headers
101 .insert("Content-Type", HeaderValue::from_static("application/json"));
102 self.method = Method::POST;
103 self.url
104 .path_segments_mut()
105 .unwrap()
106 .push("object")
107 .push("sign")
108 .push(bucket_name);
109
110 self.body = Some(BodyType::StringBody(body.to_string()));
111 self.create_executor()
112 }
113
114 /// get object via pre-signed url
115 ///
116 /// # Arguments
117 ///
118 /// * `bucket_name` - bucket name
119 /// * `object` - object name
120 /// * `token` - sign token
121 /// * `file` - file object
122 ///
123 /// # Returns
124 ///
125 /// * `Executor` - The constructed `Executor` instance for executing the request.
126 ///
127 /// # Example
128 /// ```
129 /// use supabase_storage::{
130 /// Storage,
131 /// config::SupabaseConfig,
132 /// model::bucket::NewBucket,
133 /// };
134 /// use dotenv::dotenv;
135 /// use tokio::fs::File;
136 ///
137 /// #[tokio::main]
138 /// async fn main() {
139 /// dotenv().ok();
140 /// let config = SupabaseConfig::default();
141 /// let response = Storage::new_with_config(config)
142 /// .from()
143 /// .get_object_with_pre_assigned_url("thefux", "btc.pdf", "<token>")
144 /// .execute()
145 /// .await
146 /// .unwrap();
147 /// }
148 /// ```
149 pub fn get_object_with_pre_assigned_url(
150 mut self,
151 bucket_name: &str,
152 object: &str,
153 token: &str,
154 ) -> Executor {
155 self.url
156 .path_segments_mut()
157 .unwrap()
158 .push("object")
159 .push("sign")
160 .push(bucket_name)
161 .push(object);
162
163 self.url.query_pairs_mut().append_pair("token", token);
164
165 self.create_executor()
166 }
167}
168
169#[cfg(test)]
170mod test {
171 use reqwest::{header::HeaderMap, Client, Method};
172 use url::{Host, Origin};
173
174 use crate::build::builder::{BodyType, Builder};
175
176 #[test]
177 fn test_get_object_with_signed_url() {
178 let executor = Builder::new(
179 url::Url::parse("http://localhost").unwrap(),
180 HeaderMap::new(),
181 Client::new(),
182 )
183 .get_object_with_pre_assigned_url("thefux", "btc.pdf", "token");
184
185 assert_eq!(executor.builder.method, Method::GET);
186 assert_eq!(
187 executor.builder.url.origin(),
188 Origin::Tuple("http".into(), Host::Domain("localhost".into()), 80)
189 );
190 assert_eq!(executor.builder.url.path(), "/object/sign/thefux/btc.pdf");
191 assert_eq!(executor.builder.url.query(), Some("token=token"));
192 }
193
194 #[test]
195 fn test_create_signed_url() {
196 let executor = Builder::new(
197 url::Url::parse("http://localhost").unwrap(),
198 HeaderMap::new(),
199 Client::new(),
200 )
201 .create_signed_url(
202 "thefux",
203 "btc.pdf",
204 r#"
205 {
206 "expiresIn": 3600,
207 "transform": {
208 "height": 0,
209 "width": 0,
210 "resize": "cover",
211 "format": "origin",
212 "quality": 100
213 }
214 }"#,
215 );
216
217 if let Some(typ) = executor.builder.body {
218 match typ {
219 BodyType::StringBody(val) => assert_eq!(
220 val,
221 r#"
222 {
223 "expiresIn": 3600,
224 "transform": {
225 "height": 0,
226 "width": 0,
227 "resize": "cover",
228 "format": "origin",
229 "quality": 100
230 }
231 }"#
232 ),
233 _ => panic!("nop"),
234 }
235 }
236 assert_eq!(executor.builder.method, Method::POST);
237 assert_eq!(
238 executor.builder.url.origin(),
239 Origin::Tuple("http".into(), Host::Domain("localhost".into()), 80)
240 );
241 assert_eq!(executor.builder.url.path(), "/object/sign/thefux/btc.pdf");
242 }
243
244 #[test]
245 fn test_create_signed_urls() {
246 let executor = Builder::new(
247 url::Url::parse("http://localhost").unwrap(),
248 HeaderMap::new(),
249 Client::new(),
250 )
251 .create_signed_urls("thefux", r#"{"paths":["btc.pdf","test.pdf"]}"#);
252
253 if let Some(typ) = executor.builder.body {
254 match typ {
255 BodyType::StringBody(val) => assert_eq!(val, r#"{"paths":["btc.pdf","test.pdf"]}"#),
256 _ => panic!("nop"),
257 }
258 }
259 assert_eq!(executor.builder.method, Method::POST);
260 assert_eq!(
261 executor.builder.url.origin(),
262 Origin::Tuple("http".into(), Host::Domain("localhost".into()), 80)
263 );
264 assert_eq!(executor.builder.url.path(), "/object/sign/thefux");
265 }
266}