@@ -11,8 +11,9 @@ use tauri::{
11
11
async_runtime:: Mutex ,
12
12
command,
13
13
ipc:: { CommandScope , GlobalScope } ,
14
- Manager , ResourceId , Runtime , State , Webview ,
14
+ Manager , ResourceId , ResourceTable , Runtime , State , Webview ,
15
15
} ;
16
+ use tokio:: sync:: oneshot:: { channel, Receiver , Sender } ;
16
17
17
18
use crate :: {
18
19
scope:: { Entry , Scope } ,
@@ -22,20 +23,47 @@ use crate::{
22
23
const HTTP_USER_AGENT : & str = concat ! ( env!( "CARGO_PKG_NAME" ) , "/" , env!( "CARGO_PKG_VERSION" ) , ) ;
23
24
24
25
struct ReqwestResponse ( reqwest:: Response ) ;
26
+ impl tauri:: Resource for ReqwestResponse { }
25
27
26
- type CancelableResponseResult = Result < Result < reqwest:: Response > > ;
28
+ type CancelableResponseResult = Result < reqwest:: Response > ;
27
29
type CancelableResponseFuture =
28
30
Pin < Box < dyn Future < Output = CancelableResponseResult > + Send + Sync > > ;
29
31
30
- struct FetchRequest ( Mutex < CancelableResponseFuture > ) ;
31
- impl FetchRequest {
32
- fn new ( f : CancelableResponseFuture ) -> Self {
33
- Self ( Mutex :: new ( f) )
32
+ struct FetchRequest {
33
+ fut : Mutex < CancelableResponseFuture > ,
34
+ abort_tx_rid : ResourceId ,
35
+ abort_rx_rid : ResourceId ,
36
+ }
37
+ impl tauri:: Resource for FetchRequest { }
38
+
39
+ struct AbortSender ( Sender < ( ) > ) ;
40
+ impl tauri:: Resource for AbortRecveiver { }
41
+
42
+ impl AbortSender {
43
+ fn abort ( self ) {
44
+ let _ = self . 0 . send ( ( ) ) ;
34
45
}
35
46
}
36
47
37
- impl tauri:: Resource for FetchRequest { }
38
- impl tauri:: Resource for ReqwestResponse { }
48
+ struct AbortRecveiver ( Receiver < ( ) > ) ;
49
+ impl tauri:: Resource for AbortSender { }
50
+
51
+ trait AddRequest {
52
+ fn add_request ( & mut self , fut : CancelableResponseFuture ) -> ResourceId ;
53
+ }
54
+
55
+ impl AddRequest for ResourceTable {
56
+ fn add_request ( & mut self , fut : CancelableResponseFuture ) -> ResourceId {
57
+ let ( tx, rx) = channel :: < ( ) > ( ) ;
58
+ let ( tx, rx) = ( AbortSender ( tx) , AbortRecveiver ( rx) ) ;
59
+ let req = FetchRequest {
60
+ fut : Mutex :: new ( fut) ,
61
+ abort_tx_rid : self . add ( tx) ,
62
+ abort_rx_rid : self . add ( rx) ,
63
+ } ;
64
+ self . add ( req)
65
+ }
66
+ }
39
67
40
68
#[ derive( Serialize ) ]
41
69
#[ serde( rename_all = "camelCase" ) ]
@@ -239,9 +267,9 @@ pub async fn fetch<R: Runtime>(
239
267
request = request. body ( data) ;
240
268
}
241
269
242
- let fut = async move { Ok ( request. send ( ) . await . map_err ( Into :: into) ) } ;
270
+ let fut = async move { request. send ( ) . await . map_err ( Into :: into) } ;
243
271
let mut resources_table = webview. resources_table ( ) ;
244
- let rid = resources_table. add ( FetchRequest :: new ( Box :: pin ( fut) ) ) ;
272
+ let rid = resources_table. add_request ( Box :: pin ( fut) ) ;
245
273
246
274
Ok ( rid)
247
275
} else {
@@ -260,24 +288,23 @@ pub async fn fetch<R: Runtime>(
260
288
. header ( header:: CONTENT_TYPE , data_url. mime_type ( ) . to_string ( ) )
261
289
. body ( reqwest:: Body :: from ( body) ) ?;
262
290
263
- let fut = async move { Ok ( Ok ( reqwest:: Response :: from ( response) ) ) } ;
291
+ let fut = async move { Ok ( reqwest:: Response :: from ( response) ) } ;
264
292
let mut resources_table = webview. resources_table ( ) ;
265
- let rid = resources_table. add ( FetchRequest :: new ( Box :: pin ( fut) ) ) ;
293
+ let rid = resources_table. add_request ( Box :: pin ( fut) ) ;
266
294
Ok ( rid)
267
295
}
268
296
_ => Err ( Error :: SchemeNotSupport ( scheme. to_string ( ) ) ) ,
269
297
}
270
298
}
271
299
272
300
#[ command]
273
- pub async fn fetch_cancel < R : Runtime > ( webview : Webview < R > , rid : ResourceId ) -> crate :: Result < ( ) > {
274
- let req = {
275
- let resources_table = webview. resources_table ( ) ;
276
- resources_table. get :: < FetchRequest > ( rid) ?
277
- } ;
278
- let mut req = req. 0 . lock ( ) . await ;
279
- * req = Box :: pin ( async { Err ( Error :: RequestCanceled ) } ) ;
280
-
301
+ pub fn fetch_cancel < R : Runtime > ( webview : Webview < R > , rid : ResourceId ) -> crate :: Result < ( ) > {
302
+ let mut resources_table = webview. resources_table ( ) ;
303
+ let req = resources_table. get :: < FetchRequest > ( rid) ?;
304
+ let abort_tx = resources_table. take :: < AbortSender > ( req. abort_tx_rid ) ?;
305
+ if let Some ( abort_tx) = Arc :: into_inner ( abort_tx) {
306
+ abort_tx. abort ( ) ;
307
+ }
281
308
Ok ( ( ) )
282
309
}
283
310
@@ -286,14 +313,26 @@ pub async fn fetch_send<R: Runtime>(
286
313
webview : Webview < R > ,
287
314
rid : ResourceId ,
288
315
) -> crate :: Result < FetchResponse > {
289
- let req = {
316
+ let ( req, abort_rx ) = {
290
317
let mut resources_table = webview. resources_table ( ) ;
291
- resources_table. take :: < FetchRequest > ( rid) ?
318
+ let req = resources_table. get :: < FetchRequest > ( rid) ?;
319
+ let abort_rx = resources_table. take :: < AbortRecveiver > ( req. abort_rx_rid ) ?;
320
+ ( req, abort_rx)
292
321
} ;
293
322
294
- let res = match req. 0 . lock ( ) . await . as_mut ( ) . await {
295
- Ok ( Ok ( res) ) => res,
296
- Ok ( Err ( e) ) | Err ( e) => return Err ( e) ,
323
+ let Some ( abort_rx) = Arc :: into_inner ( abort_rx) else {
324
+ return Err ( Error :: RequestCanceled ) ;
325
+ } ;
326
+
327
+ let mut fut = req. fut . lock ( ) . await ;
328
+
329
+ let res = tokio:: select! {
330
+ res = fut. as_mut( ) => res?,
331
+ _ = abort_rx. 0 => {
332
+ let mut resources_table = webview. resources_table( ) ;
333
+ resources_table. close( rid) ?;
334
+ return Err ( Error :: RequestCanceled ) ;
335
+ }
297
336
} ;
298
337
299
338
let status = res. status ( ) ;
0 commit comments