Files
platforms/apps/user_app/lib/data/services/api_client.dart

89 lines
2.7 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.
import 'dart:convert';
import 'package:http/http.dart' as http;
class ApiException implements Exception {
const ApiException(this.code, this.message);
final int code;
final String message;
@override
String toString() => message;
}
class ApiClient {
ApiClient(
this._tokenProvider, {
http.Client? client,
String? baseUrl,
}) : _client = client ?? http.Client(),
baseUrl =
baseUrl ??
const String.fromEnvironment(
'API_BASE_URL',
defaultValue: 'http://10.0.2.2:12426',
);
final String baseUrl;
final String Function() _tokenProvider;
final http.Client _client;
Future<Object?> get(String path, {bool authenticated = true}) =>
_send('GET', path, authenticated: authenticated);
Future<Object?> post(
String path, {
Map<String, Object?>? body,
bool authenticated = true,
}) => _send('POST', path, body: body, authenticated: authenticated);
Future<Object?> put(String path, {Map<String, Object?>? body}) => _send('PUT', path, body: body);
Future<Object?> delete(String path, {Map<String, Object?>? body}) =>
_send('DELETE', path, body: body);
Future<Object?> _send(
String method,
String path, {
Map<String, Object?>? body,
bool authenticated = true,
}) async {
final request = http.Request(method, Uri.parse('$baseUrl$path'));
request.headers['accept'] = 'application/json';
if (authenticated) {
final token = _tokenProvider();
if (token.isNotEmpty) request.headers['authorization'] = token;
}
if (body != null) {
request.headers['content-type'] = 'application/json; charset=UTF-8';
request.body = jsonEncode(body);
}
final streamed = await _client.send(request);
final response = await http.Response.fromStream(streamed);
if (response.statusCode < 200 || response.statusCode >= 300) {
throw ApiException(response.statusCode, '网络请求失败(${response.statusCode}');
}
final decoded = jsonDecode(response.body);
if (decoded is! Map<String, Object?>) {
throw const ApiException(500, '服务端响应格式错误');
}
final code = (decoded['code'] as num?)?.toInt() ?? 500;
if (code != 0) {
throw ApiException(code, decoded['message'] as String? ?? '操作失败');
}
return decoded['details'];
}
}
Map<String, Object?> jsonMap(Object? value) {
if (value is Map<String, Object?>) return value;
if (value is Map) return value.map((key, item) => MapEntry(key.toString(), item));
throw const ApiException(500, '服务端数据格式错误');
}
List<Map<String, Object?>> jsonList(Object? value) {
if (value is! List) return const [];
return value.map<Map<String, Object?>>(jsonMap).toList(growable: false);
}