@@ -95,6 +95,14 @@ impl<R: Runtime> fmt::Debug for InnerWindowManager<R> {
9595 }
9696}
9797
98+ /// A resolved asset.
99+ pub struct Asset {
100+ /// The asset bytes.
101+ pub bytes : Vec < u8 > ,
102+ /// The asset's mime type.
103+ pub mime_type : String ,
104+ }
105+
98106/// Uses a custom URI scheme handler to resolve file requests
99107pub struct CustomProtocol < R : Runtime > {
100108 /// Handler for protocol
@@ -371,77 +379,82 @@ impl<R: Runtime> WindowManager<R> {
371379 } )
372380 }
373381
382+ pub fn get_asset ( & self , mut path : String ) -> Result < Asset , Box < dyn std:: error:: Error > > {
383+ let assets = & self . inner . assets ;
384+ if path. ends_with ( '/' ) {
385+ path. pop ( ) ;
386+ }
387+ path = percent_encoding:: percent_decode ( path. as_bytes ( ) )
388+ . decode_utf8_lossy ( )
389+ . to_string ( ) ;
390+ let path = if path. is_empty ( ) {
391+ // if the url is `tauri://localhost`, we should load `index.html`
392+ "index.html" . to_string ( )
393+ } else {
394+ // skip leading `/`
395+ path. chars ( ) . skip ( 1 ) . collect :: < String > ( )
396+ } ;
397+ let is_javascript = path. ends_with ( ".js" ) || path. ends_with ( ".cjs" ) || path. ends_with ( ".mjs" ) ;
398+ let is_html = path. ends_with ( ".html" ) ;
399+
400+ let asset_response = assets
401+ . get ( & path. as_str ( ) . into ( ) )
402+ . or_else ( || assets. get ( & format ! ( "{}/index.html" , path. as_str( ) ) . into ( ) ) )
403+ . or_else ( || {
404+ #[ cfg( debug_assertions) ]
405+ eprintln ! ( "Asset `{}` not found; fallback to index.html" , path) ; // TODO log::error!
406+ assets. get ( & "index.html" . into ( ) )
407+ } )
408+ . ok_or_else ( || crate :: Error :: AssetNotFound ( path. clone ( ) ) )
409+ . map ( Cow :: into_owned) ;
410+
411+ match asset_response {
412+ Ok ( asset) => {
413+ let final_data = match is_javascript || is_html {
414+ true => String :: from_utf8_lossy ( & asset)
415+ . into_owned ( )
416+ . replacen (
417+ "__TAURI__INVOKE_KEY_TOKEN__" ,
418+ & self . generate_invoke_key ( ) . to_string ( ) ,
419+ 1 ,
420+ )
421+ . as_bytes ( )
422+ . to_vec ( ) ,
423+ false => asset,
424+ } ;
425+ let mime_type = MimeType :: parse ( & final_data, & path) ;
426+ Ok ( Asset {
427+ bytes : final_data,
428+ mime_type,
429+ } )
430+ }
431+ Err ( e) => {
432+ #[ cfg( debug_assertions) ]
433+ eprintln ! ( "{:?}" , e) ; // TODO log::error!
434+ Err ( Box :: new ( e) )
435+ }
436+ }
437+ }
438+
374439 #[ allow( clippy:: type_complexity) ]
375440 fn prepare_uri_scheme_protocol (
376441 & self ,
377442 ) -> Box < dyn Fn ( & HttpRequest ) -> Result < HttpResponse , Box < dyn std:: error:: Error > > + Send + Sync >
378443 {
379- let assets = self . inner . assets . clone ( ) ;
380444 let manager = self . clone ( ) ;
381445 Box :: new ( move |request| {
382- let mut path = request
446+ let path = request
383447 . uri ( )
384448 . split ( & [ '?' , '#' ] [ ..] )
385449 // ignore query string
386450 . next ( )
387451 . unwrap ( )
388452 . to_string ( )
389453 . replace ( "tauri://localhost" , "" ) ;
390- if path. ends_with ( '/' ) {
391- path. pop ( ) ;
392- }
393- path = percent_encoding:: percent_decode ( path. as_bytes ( ) )
394- . decode_utf8_lossy ( )
395- . to_string ( ) ;
396- let path = if path. is_empty ( ) {
397- // if the url is `tauri://localhost`, we should load `index.html`
398- "index.html" . to_string ( )
399- } else {
400- // skip leading `/`
401- path. chars ( ) . skip ( 1 ) . collect :: < String > ( )
402- } ;
403- let is_javascript = path. ends_with ( ".js" ) || path. ends_with ( ".cjs" ) || path. ends_with ( ".mjs" ) ;
404- let is_html = path. ends_with ( ".html" ) ;
405-
406- let asset_response = assets
407- . get ( & path. as_str ( ) . into ( ) )
408- . or_else ( || assets. get ( & format ! ( "{}/index.html" , path. as_str( ) ) . into ( ) ) )
409- . or_else ( || {
410- #[ cfg( debug_assertions) ]
411- eprintln ! ( "Asset `{}` not found; fallback to index.html" , path) ; // TODO log::error!
412- assets. get ( & "index.html" . into ( ) )
413- } )
414- . ok_or_else ( || crate :: Error :: AssetNotFound ( path. clone ( ) ) )
415- . map ( Cow :: into_owned) ;
416-
417- match asset_response {
418- Ok ( asset) => {
419- let final_data = match is_javascript || is_html {
420- true => String :: from_utf8_lossy ( & asset)
421- . into_owned ( )
422- . replacen (
423- "__TAURI__INVOKE_KEY_TOKEN__" ,
424- & manager. generate_invoke_key ( ) . to_string ( ) ,
425- 1 ,
426- )
427- . as_bytes ( )
428- . to_vec ( ) ,
429- false => asset,
430- } ;
431-
432- let mime_type = MimeType :: parse ( & final_data, & path) ;
433- Ok (
434- HttpResponseBuilder :: new ( )
435- . mimetype ( & mime_type)
436- . body ( final_data) ?,
437- )
438- }
439- Err ( e) => {
440- #[ cfg( debug_assertions) ]
441- eprintln ! ( "{:?}" , e) ; // TODO log::error!
442- Err ( Box :: new ( e) )
443- }
444- }
454+ let asset = manager. get_asset ( path) ?;
455+ HttpResponseBuilder :: new ( )
456+ . mimetype ( & asset. mime_type )
457+ . body ( asset. bytes )
445458 } )
446459 }
447460
0 commit comments