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

94 lines
3.2 KiB
Dart
Raw Normal View History

import 'dart:convert';
import 'dart:io';
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<String> upload(String filePath, {String contentType = 'image/jpeg'}) async {
final request = http.MultipartRequest('POST', Uri.parse('$baseUrl/upload/file'));
request.headers[HttpHeaders.authorizationHeader] = _tokenProvider();
request.fields['declared_content_type'] = contentType;
request.files.add(await http.MultipartFile.fromPath('file', filePath));
final response = await http.Response.fromStream(await request.send());
final details = _decode(response);
return jsonMap(details)['uri'] as String? ?? '';
}
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[HttpHeaders.acceptHeader] = 'application/json';
if (authenticated && _tokenProvider().isNotEmpty) {
request.headers[HttpHeaders.authorizationHeader] = _tokenProvider();
}
if (body != null) {
request.headers[HttpHeaders.contentTypeHeader] = 'application/json; charset=UTF-8';
request.body = jsonEncode(body);
}
final response = await http.Response.fromStream(await _client.send(request));
return _decode(response);
}
Object? _decode(http.Response response) {
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);
}