@@ -15,7 +15,7 @@ mod transfer_stats;
15
15
use transfer_stats:: TransferStats ;
16
16
17
17
use futures_util:: TryStreamExt ;
18
- use serde:: { ser:: Serializer , Serialize } ;
18
+ use serde:: { ser:: Serializer , Deserialize , Serialize } ;
19
19
use tauri:: {
20
20
command,
21
21
ipc:: Channel ,
@@ -32,6 +32,14 @@ use read_progress_stream::ReadProgressStream;
32
32
33
33
use std:: collections:: HashMap ;
34
34
35
+ #[ derive( Debug , Clone , Serialize , Deserialize ) ]
36
+ #[ serde( rename_all = "UPPERCASE" ) ]
37
+ pub enum HttpMethod {
38
+ Post ,
39
+ Put ,
40
+ Patch ,
41
+ }
42
+
35
43
type Result < T > = std:: result:: Result < T , Error > ;
36
44
37
45
#[ derive( Debug , thiserror:: Error ) ]
@@ -120,19 +128,26 @@ async fn upload(
120
128
url : String ,
121
129
file_path : String ,
122
130
headers : HashMap < String , String > ,
131
+ method : Option < HttpMethod > ,
123
132
on_progress : Channel < ProgressPayload > ,
124
133
) -> Result < String > {
125
134
tokio:: spawn ( async move {
126
135
// Read the file
127
136
let file = File :: open ( & file_path) . await ?;
128
137
let file_len = file. metadata ( ) . await . unwrap ( ) . len ( ) ;
129
138
139
+ // Get HTTP method (defaults to POST)
140
+ let http_method = method. unwrap_or ( HttpMethod :: Post ) ;
141
+
130
142
// Create the request and attach the file to the body
131
143
let client = reqwest:: Client :: new ( ) ;
132
- let mut request = client
133
- . post ( & url)
134
- . header ( reqwest:: header:: CONTENT_LENGTH , file_len)
135
- . body ( file_to_body ( on_progress, file, file_len) ) ;
144
+ let mut request = match http_method {
145
+ HttpMethod :: Put => client. put ( & url) ,
146
+ HttpMethod :: Patch => client. patch ( & url) ,
147
+ HttpMethod :: Post => client. post ( & url) ,
148
+ }
149
+ . header ( reqwest:: header:: CONTENT_LENGTH , file_len)
150
+ . body ( file_to_body ( on_progress, file, file_len) ) ;
136
151
137
152
// Loop through the headers keys and values
138
153
// and add them to the request object.
@@ -212,7 +227,7 @@ mod tests {
212
227
#[ tokio:: test]
213
228
async fn should_error_on_upload_if_status_not_success ( ) {
214
229
let mocked_server = spawn_upload_server_mocked ( 500 ) . await ;
215
- let result = upload_file ( mocked_server. url ) . await ;
230
+ let result = upload_file ( mocked_server. url , None ) . await ;
216
231
mocked_server. mocked_endpoint . assert ( ) ;
217
232
assert ! ( result. is_err( ) ) ;
218
233
match result. unwrap_err ( ) {
@@ -232,7 +247,7 @@ mod tests {
232
247
Ok ( ( ) )
233
248
} ) ;
234
249
235
- let result = upload ( mocked_server. url , file_path, headers, sender) . await ;
250
+ let result = upload ( mocked_server. url , file_path, headers, None , sender) . await ;
236
251
assert ! ( result. is_err( ) ) ;
237
252
match result. unwrap_err ( ) {
238
253
Error :: Io ( _) => { }
@@ -241,9 +256,9 @@ mod tests {
241
256
}
242
257
243
258
#[ tokio:: test]
244
- async fn should_upload_file_successfully ( ) {
259
+ async fn should_upload_file_with_post_method ( ) {
245
260
let mocked_server = spawn_upload_server_mocked ( 200 ) . await ;
246
- let result = upload_file ( mocked_server. url ) . await ;
261
+ let result = upload_file ( mocked_server. url , Some ( HttpMethod :: Post ) ) . await ;
247
262
mocked_server. mocked_endpoint . assert ( ) ;
248
263
assert ! (
249
264
result. is_ok( ) ,
@@ -254,6 +269,34 @@ mod tests {
254
269
assert_eq ! ( response_body, "upload successful" ) ;
255
270
}
256
271
272
+ #[ tokio:: test]
273
+ async fn should_upload_file_with_put_method ( ) {
274
+ let mocked_server = spawn_upload_server_mocked_with_method ( 200 , "PUT" ) . await ;
275
+ let result = upload_file ( mocked_server. url , Some ( HttpMethod :: Put ) ) . await ;
276
+ mocked_server. mocked_endpoint . assert ( ) ;
277
+ assert ! (
278
+ result. is_ok( ) ,
279
+ "failed to upload file with PUT: {}" ,
280
+ result. unwrap_err( )
281
+ ) ;
282
+ let response_body = result. unwrap ( ) ;
283
+ assert_eq ! ( response_body, "upload successful" ) ;
284
+ }
285
+
286
+ #[ tokio:: test]
287
+ async fn should_upload_file_with_patch_method ( ) {
288
+ let mocked_server = spawn_upload_server_mocked_with_method ( 200 , "PATCH" ) . await ;
289
+ let result = upload_file ( mocked_server. url , Some ( HttpMethod :: Patch ) ) . await ;
290
+ mocked_server. mocked_endpoint . assert ( ) ;
291
+ assert ! (
292
+ result. is_ok( ) ,
293
+ "failed to upload file with PATCH: {}" ,
294
+ result. unwrap_err( )
295
+ ) ;
296
+ let response_body = result. unwrap ( ) ;
297
+ assert_eq ! ( response_body, "upload successful" ) ;
298
+ }
299
+
257
300
async fn download_file ( url : String ) -> Result < ( ) > {
258
301
let file_path = concat ! ( env!( "CARGO_MANIFEST_DIR" ) , "/test/test.txt" ) . to_string ( ) ;
259
302
let headers = HashMap :: new ( ) ;
@@ -265,15 +308,15 @@ mod tests {
265
308
download ( url, file_path, headers, None , sender) . await
266
309
}
267
310
268
- async fn upload_file ( url : String ) -> Result < String > {
311
+ async fn upload_file ( url : String , method : Option < HttpMethod > ) -> Result < String > {
269
312
let file_path = concat ! ( env!( "CARGO_MANIFEST_DIR" ) , "/test/test.txt" ) . to_string ( ) ;
270
313
let headers = HashMap :: new ( ) ;
271
314
let sender: Channel < ProgressPayload > =
272
315
Channel :: new ( |msg : InvokeResponseBody | -> tauri:: Result < ( ) > {
273
316
let _ = msg;
274
317
Ok ( ( ) )
275
318
} ) ;
276
- upload ( url, file_path, headers, sender) . await
319
+ upload ( url, file_path, headers, method , sender) . await
277
320
}
278
321
279
322
async fn spawn_server_mocked ( return_status : usize ) -> MockedServer {
@@ -295,10 +338,17 @@ mod tests {
295
338
}
296
339
297
340
async fn spawn_upload_server_mocked ( return_status : usize ) -> MockedServer {
341
+ spawn_upload_server_mocked_with_method ( return_status, "POST" ) . await
342
+ }
343
+
344
+ async fn spawn_upload_server_mocked_with_method (
345
+ return_status : usize ,
346
+ method : & str ,
347
+ ) -> MockedServer {
298
348
let mut _server = Server :: new_async ( ) . await ;
299
349
let path = "/upload_test" ;
300
350
let mock = _server
301
- . mock ( "POST" , path)
351
+ . mock ( method , path)
302
352
. with_status ( return_status)
303
353
. with_body ( "upload successful" )
304
354
. match_header ( "content-length" , "20" )
0 commit comments