|
import 'dart:async';
|
|
import 'dart:developer';
|
|
import '../constants/constants.dart';
|
|
import '../constants/urls.dart';
|
|
import 'package:http/http.dart' as http;
|
|
|
|
abstract class ApiClient {
|
|
int timeoutSeconds = 60;
|
|
http.Client client = http.Client();
|
|
|
|
Future<http.Response> get(
|
|
String partOfUrl, {
|
|
Map<String, dynamic>? queryParams,
|
|
bool isFirebaseCall = false,
|
|
bool isTesting = false,
|
|
}) async {
|
|
return sendRequest(
|
|
_buildUrlWithParams(partOfUrl, _mapToParams(queryParams)),
|
|
method: 'GET',
|
|
isFirebaseCall: isFirebaseCall,
|
|
retryOn401: true,
|
|
);
|
|
}
|
|
|
|
Future<http.Response> post(
|
|
String partOfUrl,
|
|
String body, {
|
|
bool isFirebaseCall = false,
|
|
bool isTesting = false,
|
|
}) async {
|
|
return sendRequest(
|
|
partOfUrl,
|
|
method: 'POST',
|
|
body: body,
|
|
isFirebaseCall: isFirebaseCall,
|
|
retryOn401: true,
|
|
);
|
|
}
|
|
|
|
Future<http.Response> put(
|
|
String partOfUrl,
|
|
String body, {
|
|
bool isFirebaseCall = false,
|
|
bool isTesting = false,
|
|
}) async {
|
|
return sendRequest(
|
|
partOfUrl,
|
|
method: 'PUT',
|
|
body: body,
|
|
isFirebaseCall: isFirebaseCall,
|
|
retryOn401: true,
|
|
);
|
|
}
|
|
|
|
Future<http.Response> delete(
|
|
String partOfUrl,
|
|
String body, {
|
|
bool isFirebaseCall = false,
|
|
}) async {
|
|
return sendRequest(
|
|
partOfUrl,
|
|
method: 'DELETE',
|
|
body: body,
|
|
isFirebaseCall: isFirebaseCall,
|
|
retryOn401: true,
|
|
);
|
|
}
|
|
|
|
Future<http.Response> sendRequest(
|
|
String partOfUrl, {
|
|
required String method,
|
|
String? body,
|
|
required bool retryOn401,
|
|
required bool isFirebaseCall,
|
|
}) async {
|
|
http.Response response = http.Response('{}', 408);
|
|
|
|
try {
|
|
final headers = {
|
|
'Accept-Encoding': 'gzip',
|
|
'Accept-Language': 'en',
|
|
if (method != 'GET') 'Content-Type': 'application/json',
|
|
};
|
|
|
|
final baseUrl = URLs.fullApiUrl;
|
|
final url = partOfUrl.contains(URLs.version)
|
|
? partOfUrl
|
|
: (baseUrl + partOfUrl);
|
|
|
|
response = await executeRequest(url, method, headers, body: body);
|
|
|
|
// Handle non-success codes
|
|
if (!Constants.isSuccessCode(response.statusCode)) {
|
|
Constants.logger.w(
|
|
'$method $url failed with ${response.statusCode}. Body: ${response.body}',
|
|
);
|
|
}
|
|
|
|
return response;
|
|
} catch (e) {
|
|
return response;
|
|
}
|
|
}
|
|
|
|
Future<http.Response> executeRequest(
|
|
String url,
|
|
String method,
|
|
Map<String, String> headers, {
|
|
String? body = '{}',
|
|
}) {
|
|
if (body != null && body.length > 200) {
|
|
log('$method $url\nBody: $body');
|
|
} else {
|
|
Constants.logger.f('$method $url\nBody: $body');
|
|
}
|
|
|
|
final uri = Uri.parse(url);
|
|
final timeout = Duration(seconds: timeoutSeconds);
|
|
|
|
switch (method.toUpperCase()) {
|
|
case 'GET':
|
|
return client.get(uri, headers: headers).timeout(timeout);
|
|
case 'POST':
|
|
return client.post(uri, headers: headers, body: body).timeout(timeout);
|
|
case 'PUT':
|
|
return client.put(uri, headers: headers, body: body).timeout(timeout);
|
|
case 'DELETE':
|
|
return client
|
|
.delete(uri, headers: headers, body: body)
|
|
.timeout(timeout);
|
|
default:
|
|
throw UnsupportedError('HTTP method $method not supported');
|
|
}
|
|
}
|
|
|
|
List<String>? _mapToParams(Map<String, dynamic>? params) {
|
|
return params?.entries
|
|
.map(
|
|
(e) => e.value != null && e.value.toString().isNotEmpty
|
|
? '${e.key}=${e.value}'
|
|
: '',
|
|
)
|
|
.toList();
|
|
}
|
|
|
|
String _buildUrlWithParams(String url, List<String>? params) {
|
|
if (params != null) {
|
|
params = params.where((p) => p.isNotEmpty).toList();
|
|
}
|
|
return params?.isEmpty ?? true
|
|
? url
|
|
: '$url${url.contains('?') ? '&' : '?'}${params!.join('&')}';
|
|
}
|
|
}
|