aves_mio1/lib/remote/remote_http.dart
FabioMich66 084fa184da
Some checks failed
Quality check / Flutter analysis (push) Has been cancelled
Quality check / CodeQL analysis (java-kotlin) (push) Has been cancelled
ok con video e foto in galleria aves
2026-03-17 12:19:38 +01:00

104 lines
3.6 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// lib/remote/remote_http.dart
import 'dart:developer' as dev;
import 'package:flutter/services.dart';
import 'remote_settings.dart';
import 'auth_client.dart';
/// Helper HTTP per risorse remote (URL + headers di autenticazione).
class RemoteHttp {
static RemoteAuth? _auth;
static String? _base;
// Cache dell'ultimo set di header (mai null: {} se non autenticato)
static Map<String, String> _cachedHeaders = const {};
static Future<void>? _initFuture; // evita init concorrenti
/// Inizializza auth e base URL dai settings sicuri (robusto: non lancia).
static Future<void> init() {
_initFuture ??= _doInit();
return _initFuture!;
}
static Future<void> _doInit() async {
try {
final s = await RemoteSettings.load(); // safe lato storage
final base = s.baseUrl.trim();
_base = base.isEmpty ? null : base;
_auth = RemoteAuth(baseUrl: s.baseUrl, email: s.email, password: s.password);
dev.log('[RemoteHttp] init: base=$_base, email=${s.email.isNotEmpty ? '***' : '(none)'}', name: 'RemoteHttp');
} catch (e, st) {
dev.log('[RemoteHttp] init ERROR: $e', name: 'RemoteHttp', error: e, stackTrace: st);
_auth = null;
_base = null;
}
}
/// Headers correnti (login ondemand). Non lancia; ritorna {} se non disponibili.
static Future<Map<String, String>> headers() async {
if (_auth == null) {
await init();
if (_auth == null) {
_cachedHeaders = const {};
dev.log('[RemoteHttp] headers: init failed → NO TOKEN', name: 'RemoteHttp');
return _cachedHeaders;
}
}
try {
final h = await _auth!.authHeaders(); // login on-demand
_cachedHeaders = Map<String, String>.from(h);
if ((_cachedHeaders['Authorization']?.isEmpty ?? true)) {
dev.log('[RemoteHttp] headers: NO Authorization', name: 'RemoteHttp');
} else {
dev.log('[RemoteHttp] headers: Authorization: Bearer ***', name: 'RemoteHttp');
}
return _cachedHeaders;
} on PlatformException catch (e, st) {
// Tipico: secure storage/keystore corrotto → non rompiamo la UI
dev.log('[RemoteHttp] headers PlatformException: $e → returning {}',
name: 'RemoteHttp', error: e, stackTrace: st);
_cachedHeaders = const {};
return _cachedHeaders;
} catch (e, st) {
dev.log('[RemoteHttp] headers ERROR: $e → returning {}',
name: 'RemoteHttp', error: e, stackTrace: st);
_cachedHeaders = const {};
return _cachedHeaders;
}
}
/// Ultimi header noti (sincrono). Mai null; {} se non autenticato.
static Map<String, String> peekHeaders() => _cachedHeaders;
/// Converte path relativo in assoluto. Se è già http/https lo ritorna comè.
static String absUrl(String? relativePath) {
if (relativePath == null || relativePath.isEmpty) return '';
final lp = relativePath.trim().toLowerCase();
if (lp.startsWith('http://') || lp.startsWith('https://')) {
return relativePath;
}
if (_base == null || _base!.isEmpty) return '';
final b = _base!.endsWith('/') ? _base! : '${_base!}/';
final rel = relativePath.startsWith('/') ? relativePath.substring(1) : relativePath;
return '$b$rel';
}
/// Facoltativo: warmup allavvio per scaldare gli header.
static Future<void> warmUp() async {
await init();
try {
await headers();
} catch (_) {
// già loggato in headers()
}
}
/// Rilegge i settings a runtime (es. utente cambia base/email/password).
static Future<void> refreshFromSettings() async {
_initFuture = null;
await init();
_cachedHeaders = const {}; // saranno ricaricati al primo uso
}
}