11use std:: {
22 convert:: TryFrom ,
3- env :: { self , VarError } ,
4- path:: PathBuf ,
3+ fs ,
4+ path:: { Path , PathBuf } ,
55 time:: Duration ,
66} ;
77
@@ -15,9 +15,27 @@ use serde::{Deserialize, Serialize};
1515use serde_json:: Deserializer ;
1616use stremio_core:: runtime:: { EnvError , EnvFutureExt , TryEnvFuture } ;
1717
18+ use crate :: CACHE_DIR ;
19+
1820static CLIENT_WITH_CACHE : OnceCell < ClientWithMiddleware > = OnceCell :: new ( ) ;
1921static CLIENT_WITHOUT_CACHE : OnceCell < ClientWithMiddleware > = OnceCell :: new ( ) ;
2022
23+ /// 1. Creates all directories for the path if they don't exist
24+ /// 2. writes a test file to see if the app has write permission
25+ /// 3. deletes the file to clean up and check delete permission
26+ fn ensure_cache_dir_permissions ( path : & Path ) -> std:: io:: Result < ( ) > {
27+ // Ensure directory exists
28+ fs:: create_dir_all ( path) ?;
29+
30+ // Attempt to create a temp file
31+ let test_file = path. join ( ".cache_permission_test" ) ;
32+ fs:: write ( & test_file, b"test" ) ?;
33+
34+ // Attempt to delete it
35+ fs:: remove_file ( & test_file) ?;
36+ Ok ( ( ) )
37+ }
38+
2139pub fn fetch < IN : Serialize + Send + ' static , OUT : for < ' de > Deserialize < ' de > + Send + ' static > (
2240 request : Request < IN > ,
2341) -> TryEnvFuture < OUT > {
@@ -33,48 +51,49 @@ pub fn fetch<IN: Serialize + Send + 'static, OUT: for<'de> Deserialize<'de> + Se
3351 Err ( error) => return future:: err ( EnvError :: Fetch ( error. to_string ( ) ) ) . boxed_env ( ) ,
3452 } ;
3553
36- let client = match env:: var ( "TMPDIR" ) {
37- Ok ( tmpdir) => {
38- CLIENT_WITH_CACHE . get_or_init ( || {
39- let tmpdir_path = PathBuf :: from ( tmpdir) ;
40- let cacache_path = tmpdir_path. join ( "http-cacache" ) ;
41- let connection_timeout = Duration :: from_secs ( 30 ) ;
54+ let fut = async {
55+ // should always be set as we set it on initializeNative
56+ let client = CACHE_DIR . get ( ) . cloned ( ) . flatten ( ) . and_then ( |cache_dir| {
57+ let cacache_path = PathBuf :: from ( cache_dir) ;
58+
59+ match ensure_cache_dir_permissions ( & cacache_path) {
60+ Ok ( _) => {
4261
43- tracing:: info!( tmpdir_path = %tmpdir_path. display( ) , cacache_path = %cacache_path. display( ) , ?connection_timeout, "Client Cacache middleware will be initialized..." ) ;
62+ let cacache_manager = CACacheManager { path : cacache_path. clone ( ) } ;
63+
64+ Some ( CLIENT_WITH_CACHE . get_or_init ( || {
65+ let connection_timeout = Duration :: from_secs ( 30 ) ;
66+
67+ tracing:: info!( cacache_path = %cacache_path. display( ) , ?connection_timeout, "Client CACache middleware will be initialized..." ) ;
68+ ClientBuilder :: new (
69+ Client :: builder ( )
70+ . connect_timeout ( connection_timeout)
71+ . use_rustls_tls ( )
72+ . build ( )
73+ . unwrap_or_default ( ) ,
74+ )
75+ . with ( Cache ( HttpCache {
76+ mode : CacheMode :: Default ,
77+ manager : cacache_manager,
78+ options : HttpCacheOptions :: default ( ) ,
79+ } ) )
80+ . build ( )
81+ } ) )
82+ } ,
83+ Err ( _) => None ,
84+ }
85+ } ) . unwrap_or_else ( || { CLIENT_WITHOUT_CACHE . get_or_init ( || {
4486 ClientBuilder :: new (
4587 Client :: builder ( )
46- . connect_timeout ( connection_timeout )
88+ . connect_timeout ( Duration :: from_secs ( 30 ) )
4789 . use_rustls_tls ( )
4890 . build ( )
4991 . unwrap_or_default ( ) ,
5092 )
51- . with ( Cache ( HttpCache :: < CACacheManager > {
52- mode : CacheMode :: Default ,
53- manager : CACacheManager {
54- path : cacache_path,
55- } ,
56- options : HttpCacheOptions :: default ( ) ,
57- } ) )
5893 . build ( )
5994 } )
60- }
61- Err ( err) => CLIENT_WITHOUT_CACHE . get_or_init ( || {
62- // we log the error only once when initializing the Client.
63- if let VarError :: NotUnicode ( _) = & err {
64- tracing:: error!( ?err, "TMPDIR env. variable is not a valid Unicode, no Client Cacache middleware will be used" ) ;
65- }
66- ClientBuilder :: new (
67- Client :: builder ( )
68- . connect_timeout ( Duration :: from_secs ( 30 ) )
69- . use_rustls_tls ( )
70- . build ( )
71- . unwrap_or_default ( ) ,
72- )
73- . build ( )
74- } )
75- } ;
95+ } ) ;
7696
77- let fut = async {
7897 let resp = client
7998 . execute ( request)
8099 . map_err ( |error| EnvError :: Fetch ( error. to_string ( ) ) )
0 commit comments