fetchConfigFromCDN function
Fetches configuration from CDN with automatic caching This function never throws errors - it always returns a valid config from cache, CDN, or local file
Strategy:
- Check if cache is valid (within 5 minutes) -> return cached config
- If cache invalid/missing -> fetch from CDN URL
- If CDN fetch fails -> try to return stored config
- If all fails -> return local bundled kp-config.json
@param options CDN configuration options @returns Future
Implementation
Future<CDNConfig> fetchConfigFromCDN([CDNConfigOptions? options]) async {
// Ensure CDN config is initialized
await cdnConfigInstance.initialize();
try {
final opts = CDNConfigOptions();
// Strategy 1: Check cache validity first
final isValid = await cdnConfigInstance.isCacheValid();
if (isValid) {
final cachedConfig = await cdnConfigInstance.getCachedConfig();
if (cachedConfig != null) {
// Alert: Config fetched from local cache
_showConfigSourceNotification('Config loaded from local cache', isLocal: true);
return cachedConfig;
}
}
// Strategy 2: Cache is invalid or doesn't exist, fetch from CDN
final url = '${opts.cdnBaseUrl}${opts.configPath}.json';
try {
// Alert: Fetching config from remote CDN
_showConfigSourceNotification('Fetching config from remote CDN...', isLocal: false);
final dio = Dio();
final response = await dio.get(
url,
options: Options(
headers: {
'Accept': 'application/json',
'User-Agent': 'KwikPass-SDK-Flutter',
},
receiveTimeout: const Duration(seconds: 10),
sendTimeout: const Duration(seconds: 10),
),
);
if (response.statusCode == 200) {
// Process the CDN response (handles minified JSON)
final jsonData = response.data is String
? jsonDecode(response.data as String) as Map<String, dynamic>
: response.data as Map<String, dynamic>;
final processedConfig = cdnConfigInstance.processCDNResponse(jsonData);
// Cache the fresh config with new timestamp
await cdnConfigInstance.cacheConfig(processedConfig);
// Alert: Successfully fetched from remote CDN
_showConfigSourceNotification('Config successfully fetched from remote CDN', isLocal: false);
return processedConfig;
} else {
throw Exception('CDN returned status code: ${response.statusCode}');
}
} catch (cdnError) {
// print('[CDN Config] ⚠️ CDN fetch failed: $cdnError');
// Strategy 3: Try to return existing stored config if valid
try {
final storedConfig = await cdnConfigInstance.getStoredCDNConfig();
if (storedConfig != null) {
// Alert: Using stored config as fallback
_showConfigSourceNotification('Using stored config (CDN unavailable)', isLocal: true);
return storedConfig;
}
} catch (storageError) {
// print('[CDN Config] ⚠️ Failed to retrieve stored config: $storageError');
}
// Strategy 4: Final fallback - use the local kp-config.json file
// Alert: Using local bundled config as final fallback
_showConfigSourceNotification('Using local bundled config (fallback)', isLocal: true);
final localConfig = await _loadLocalConfig();
// Cache the local config for future use
try {
await cdnConfigInstance.cacheConfig(localConfig);
} catch (cacheError) {
// print('[CDN Config] ⚠️ Failed to cache local config: $cacheError');
}
return localConfig;
}
} catch (error) {
// Ultimate fallback - if everything fails, return local config
// print('[CDN Config] ❌ Unexpected error, using local kp-config.json: $error');
return await _loadLocalConfig();
}
}