get method

Future<PlexApiResponse> get(
  1. String url, {
  2. Map<String, dynamic>? query,
  3. Map<String, String>? headers,
  4. Duration? timeout,
  5. PlexCancelToken? cancelToken,
})

Implementation

Future<PlexApiResponse> get(
  String url, {
  Map<String, dynamic>? query,
  Map<String, String>? headers,
  Duration? timeout,
  PlexCancelToken? cancelToken,
}) async {
  if (await isNetworkAvailable() == false) {
    return PlexNetworkNoConnectivity();
  }

  final baseUrl = url;
  if (query != null && query.isNotEmpty) {
    url += "?";
    query.forEach((key, value) {
      url += "$key=$value&";
    });
    url = url.substring(0, url.length - 1);
  }

  if (_cacheLayer != null) {
    final cachedBody = await _cacheLayer!.get(baseUrl, query);
    if (cachedBody != null) {
      return _runResponseInterceptors(PlexSuccess(cachedBody));
    }
  }

  var currentHeaders = <String, String>{};
  if (addHeaders != null) {
    currentHeaders.addAll(await addHeaders!());
  }
  if (headers != null) {
    currentHeaders.addAll(headers);
  }
  if (!currentHeaders.containsKey("Content-Type")) {
    currentHeaders["Content-Type"] = "application/json";
  }
  currentHeaders = await _runRequestInterceptors(url, currentHeaders);

  final retry = _retryInterceptor;
  final maxAttempts = retry?.maxAttempts ?? 1;
  var lastResponse = PlexNetworkNoConnectivity() as PlexApiResponse;
  final requestTimeout = timeout ?? defaultTimeout;

  for (var attempt = 0; attempt < maxAttempts; attempt++) {
    if (cancelToken?.isCancelled == true) {
      lastResponse = PlexNetworkCancelled();
      break;
    }
    try {
      var startTime = DateTime.now();
      var uri = Uri.parse(_isValidUrl(url) ? url : _apiUrl() + url);
      PlexLogger.d('Networking', 'Started: ${uri.toString()}');

      var data = await http.get(uri, headers: currentHeaders).timeout(requestTimeout);
      if (cancelToken?.isCancelled == true) {
        lastResponse = PlexNetworkCancelled();
        break;
      }
      var diffInMillis = DateTime.now().difference(startTime).inMilliseconds;
      PlexLogger.d('Networking', 'Completed: ${data.statusCode}: ${uri.toString()} in ${diffInMillis}ms');

      if (data.statusCode == 200) {
        await _cacheLayer?.put(baseUrl, query, data.body);
        lastResponse = PlexSuccess(data.body);
      } else {
        lastResponse = PlexNetworkServerError(
          data.statusCode,
          data.body.isEmpty ? (data.reasonPhrase ?? data.body) : data.body,
        );
      }

      final statusCode = lastResponse is PlexNetworkServerError ? lastResponse.statusCode : 0;
      final shouldRetry = lastResponse is PlexNetworkServerError && retry != null && retry.retryOnStatusCodes.contains(statusCode) && attempt < maxAttempts - 1;
      if (!shouldRetry) break;
    } catch (e, stack) {
      if (e is TimeoutException) {
        lastResponse = PlexNetworkTimeout();
      } else if (e is SocketException) {
        lastResponse = PlexNetworkNoConnectivity();
      } else {
        PlexLogger.e('Networking', 'Request failed', error: e);
        lastResponse = await _runErrorInterceptors(e, stack);
      }
      break;
    }
  }

  return _runResponseInterceptors(lastResponse);
}