69 lines
2.2 KiB
Dart
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();
|
|
}
|
|
}
|
|
}
|