send method
Sends a single HTTP request built with the current client configuration and the provided options.
All response errors are normalized and wrapped in ClientException.
Implementation
Future<dynamic> send(
String path, {
String method = "GET",
Map<String, String> headers = const {},
Map<String, dynamic> query = const {},
Map<String, dynamic> body = const {},
List<http.MultipartFile> files = const [],
}) async {
http.BaseRequest request;
final url = buildUrl(path, query);
if (files.isEmpty) {
request = _jsonRequest(method, url, headers: headers, body: body);
} else {
request = _multipartRequest(
method,
url,
headers: headers,
body: body,
files: files,
);
}
if (!headers.containsKey("Authorization") && authStore.isValid) {
request.headers["Authorization"] = authStore.token;
}
if (!headers.containsKey("Accept-Language")) {
request.headers["Accept-Language"] = lang;
}
// ensures that keepalive on web is disabled for now
//
// it is ignored anyway when using the default http.Cient on web
// and it causing issues with the alternative fetch_client package
// (see https://github.com/Zekfad/fetch_client/issues/6#issuecomment-1615936365)
if (isWeb) {
request.persistentConnection = false;
}
final requestClient = httpClientFactory();
try {
final response = await requestClient.send(request);
final responseStr = await response.stream.bytesToString();
dynamic responseData;
try {
responseData = responseStr.isNotEmpty ? jsonDecode(responseStr) : null;
} catch (_) {
// custom non-json response
responseData = responseStr;
}
if (response.statusCode >= 400) {
throw ClientException(
url: url,
statusCode: response.statusCode,
response: responseData is Map<String, dynamic> ? responseData : {},
);
}
return responseData;
} catch (e) {
// PocketBase API exception
if (e is ClientException) {
rethrow;
}
// http client exception (eg. connection abort)
if (e is http.ClientException) {
throw ClientException(
url: e.uri,
originalError: e,
// @todo will need to be redefined once cancellation support is added
isAbort: true,
);
}
// anything else
throw ClientException(url: url, originalError: e);
} finally {
requestClient.close();
}
}