import 'dart:convert'; import 'package:http/http.dart' as http; class ApiClient { ApiClient( this.baseUrl, { this.getAccessToken, this.onUnauthorized, }); final String baseUrl; // z.B. https://api.windesign.at/hedgehogs.php?r= final Future Function()? getAccessToken; final Future Function()? onUnauthorized; Future _send(String method, String path, {Object? body}) async { final uri = Uri.parse('$baseUrl$path'); final headers = {'Content-Type': 'application/json'}; final token = await getAccessToken?.call(); if (token != null) headers['Authorization'] = 'Bearer $token'; switch (method) { case 'GET': return http.get(uri, headers: headers); case 'POST': return http.post(uri, headers: headers, body: body == null ? null : jsonEncode(body)); case 'PUT': return http.put(uri, headers: headers, body: body == null ? null : jsonEncode(body)); case 'DELETE': return http.delete(uri, headers: headers); default: throw UnimplementedError(method); } } Future _requestWithRetry(String method, String path, {Object? body}) async { var res = await _send(method, path, body: body); if (res.statusCode == 401 && onUnauthorized != null) { await onUnauthorized!.call(); res = await _send(method, path, body: body); } if (res.statusCode >= 200 && res.statusCode < 300) { if (res.body.isEmpty) return (null as T); final decoded = jsonDecode(res.body); return decoded as T; } throw ApiException(res.statusCode, res.body); } Future get(String path) async => _requestWithRetry('GET', path); Future post(String path, Object body) async => _requestWithRetry('POST', path, body: body); Future put(String path, Object body) async => _requestWithRetry('PUT', path, body: body); Future delete(String path) async => _requestWithRetry('DELETE', path); } class ApiException implements Exception { final int status; final String body; ApiException(this.status, this.body); @override String toString() => 'ApiException($status): $body'; }