@@ -2,12 +2,14 @@ use cloudflare::framework::client::async_api::Client as HttpApiClientAsync;
22use cloudflare:: framework:: { Environment , response:: ApiFailure } ;
33use cloudflare:: endpoints:: zones:: zone:: { ListZones , ListZonesParams } ;
44use lazy_static:: lazy_static;
5+ use tokio:: sync:: RwLockWriteGuard ;
56use std:: collections:: HashMap ;
6- use std :: sync:: RwLock ;
7+ use tokio :: sync:: RwLock ;
78use super :: auth_manager:: AuthManager ;
9+ use std:: sync:: Arc ;
810
911lazy_static ! {
10- static ref ZONE_CACHE : RwLock <HashMap <String , String >> = RwLock :: new( HashMap :: new( ) ) ;
12+ static ref ZONE_CACHE : Arc < RwLock <HashMap <String , String >>> = Arc :: new ( RwLock :: new( HashMap :: new( ) ) ) ;
1113}
1214
1315pub struct ZoneManager { }
@@ -24,41 +26,69 @@ impl ZoneManager {
2426 api_token : Option < String > ,
2527 ) -> Result < ( ) , String > {
2628 let credentials = AuthManager :: get_credentials ( email, api_key, api_token) ?;
27-
28- // Corrected client instantiation
29+
2930 let client = HttpApiClientAsync :: new (
3031 credentials,
3132 Default :: default ( ) ,
3233 Environment :: Production ,
33- ) . map_err ( |e| format ! ( "Cloudflare API client creation failed: {:?}" , e) ) ?;
34-
35- let endpoint = ListZones {
36- params : ListZonesParams :: default ( ) ,
37- } ;
38-
34+ )
35+ . map_err ( |e| format ! ( "Cloudflare API client creation failed: {:?}" , e) ) ?;
36+
37+ let mut page = 1 ;
38+ let per_page = 50 ;
39+ let mut fetched_all = false ;
40+
41+ {
42+ let mut cache: RwLockWriteGuard < ' _ , HashMap < String , String > > = ZONE_CACHE . write ( ) . await ;
43+ cache. clear ( ) ;
44+ }
45+
3946 println ! ( "# Retrieving zones from Cloudflare API..." ) ;
40-
41- // Make the async request using the correct client & endpoints
42- match client. request ( & endpoint) . await {
43- Ok ( api_success) => {
44- let zones = api_success. result ;
45- let mut cache = ZONE_CACHE . write ( ) . map_err ( |e| format ! ( "Cache write lock error: {}" , e) ) ?;
46- cache. clear ( ) ;
47- for zone in & zones {
48- println ! ( "# Zone found: {} ({})" , zone. name, zone. id) ;
49- cache. insert ( zone. name . clone ( ) , zone. id . clone ( ) ) ;
47+ while !fetched_all {
48+ let params = ListZonesParams {
49+ page : Some ( page) ,
50+ per_page : Some ( per_page) ,
51+ ..Default :: default ( )
52+ } ;
53+ let endpoint = ListZones { params } ;
54+
55+ match client. request ( & endpoint) . await {
56+ Ok ( api_success) => {
57+ let zones = api_success. result ;
58+
59+ {
60+ let mut cache = ZONE_CACHE . write ( ) . await ;
61+ for zone in & zones {
62+ println ! ( "# Zone found: {} ({})" , zone. name, zone. id) ;
63+ cache. insert ( zone. name . clone ( ) , zone. id . clone ( ) ) ;
64+ }
65+ }
66+
67+ if let Some ( result_info) = api_success. result_info {
68+ if let Some ( total_pages) = result_info. get ( "total_pages" ) . and_then ( |v| v. as_u64 ( ) ) {
69+ if page >= total_pages as u32 {
70+ fetched_all = true ;
71+ } else {
72+ page += 1 ;
73+ }
74+ } else {
75+ fetched_all = true ;
76+ }
77+ } else {
78+ fetched_all = true ;
79+ }
80+ }
81+ Err ( ApiFailure :: Error ( status, errors) ) => {
82+ println ! ( "# Cloudflare API returned error (HTTP {}): {:?}" , status, errors) ;
83+ return Err ( format ! ( "Cloudflare API error ({}): {:?}" , status, errors) ) ;
84+ }
85+ Err ( ApiFailure :: Invalid ( e) ) => {
86+ println ! ( "# HTTP request failure: {:?}" , e) ;
87+ return Err ( format ! ( "Cloudflare HTTP request failed: {}" , e) ) ;
5088 }
51- Ok ( ( ) )
52- }
53- Err ( ApiFailure :: Error ( status, errors) ) => {
54- println ! ( "# Cloudflare API returned error (HTTP {}): {:?}" , status, errors) ;
55- Err ( format ! ( "Cloudflare API error ({}): {:?}" , status, errors) )
56- }
57- Err ( ApiFailure :: Invalid ( e) ) => {
58- println ! ( "# HTTP request failure: {:?}" , e) ;
59- Err ( format ! ( "Cloudflare HTTP request failed: {}" , e) )
6089 }
6190 }
91+ Ok ( ( ) )
6292 }
6393
6494 pub async fn find_best_matching_zone (
@@ -69,20 +99,20 @@ impl ZoneManager {
6999 api_token : Option < String > ,
70100 ) -> Result < ( Option < String > , Option < String > ) , String > {
71101 // Try to find from cache first
72- if let Some ( ( zone_name, zone_id) ) = Self :: find_best_match_from_cache ( hostname) {
102+ if let Some ( ( zone_name, zone_id) ) = Self :: find_best_match_from_cache ( hostname) . await {
73103 return Ok ( ( Some ( zone_name) , Some ( zone_id) ) ) ;
74104 }
75105
76106 // If not found in cache, refresh zones and try again
77107 self . refresh_zones ( email, api_key, api_token) . await ?;
78108
79109 // Return the best match after refresh
80- Ok ( Self :: find_best_match_from_cache ( hostname) . map ( |( name, id) | ( Some ( name) , Some ( id) ) ) . unwrap_or ( ( None , None ) ) )
110+ Ok ( Self :: find_best_match_from_cache ( hostname) . await . map ( |( name, id) | ( Some ( name) , Some ( id) ) ) . unwrap_or ( ( None , None ) ) )
81111 }
82112
83113 /// Helper method to find the best matching zone from the cache
84- fn find_best_match_from_cache ( hostname : & str ) -> Option < ( String , String ) > {
85- let cache = ZONE_CACHE . read ( ) . ok ( ) ? ;
114+ async fn find_best_match_from_cache ( hostname : & str ) -> Option < ( String , String ) > {
115+ let cache = ZONE_CACHE . read ( ) . await ;
86116
87117 // Find all zone names that are part of the hostname (domain matching)
88118 // A proper match is when the hostname ends with the zone name,
0 commit comments