Files
companion/lib/data/sources/localiser/localiser_client.dart
T
2026-05-07 18:35:58 +02:00

69 lines
2.2 KiB
Dart

import 'dart:convert';
import 'dart:io';
import '../../../domain/models/server_config.dart';
class ApiException implements Exception {
const ApiException(this.statusCode, this.message);
final int statusCode;
final String message;
@override
String toString() => 'ApiException $statusCode: $message';
}
abstract class LocaliserdClient {
const LocaliserdClient({required this.config, this.token});
final ServerConfig config;
/// Null for unauthenticated clients (session, onboarding setup).
final String? token;
Uri _uri(String path) => Uri(
scheme: 'http',
host: config.host,
port: config.port,
path: path,
);
Future<dynamic> get(String path) => _request('GET', path);
Future<dynamic> post(String path, [Object? body]) => _request('POST', path, body);
Future<dynamic> put(String path, [Object? body]) => _request('PUT', path, body);
Future<dynamic> patch(String path, [Object? body]) => _request('PATCH', path, body);
Future<void> delete(String path) => _request('DELETE', path).then((_) {});
/// Like [delete] but returns the response body (for endpoints that do so).
Future<dynamic> deleteBody(String path) => _request('DELETE', path);
Future<dynamic> _request(String method, String path, [Object? body]) async {
final http = HttpClient();
try {
final request = await http.openUrl(method, _uri(path));
request.headers.contentType = ContentType.json;
if (token != null) {
request.headers.set(HttpHeaders.authorizationHeader, 'Bearer $token');
}
if (body != null) request.write(jsonEncode(body));
final response = await request.close();
if (response.statusCode == 204) return null;
final responseBody = await response.transform(utf8.decoder).join();
if (response.statusCode >= 400) {
final parsed = responseBody.isNotEmpty
? jsonDecode(responseBody) as Map<String, dynamic>?
: null;
throw ApiException(
response.statusCode,
parsed?['error']?.toString() ?? responseBody,
);
}
return responseBody.isEmpty ? null : jsonDecode(responseBody);
} finally {
http.close();
}
}
}