makeTrayRequest<ModelType> function

Future<TrayRequestResponse<ModelType>> makeTrayRequest<ModelType>(
  1. TrayRequest request, {
  2. Client? client,
  3. FetchTrayDebugLevel? requestDebugLevel,
})

makes the process of requesting data from an api endpoint easier it takes care of making the request and mocking

Implementation

Future<TrayRequestResponse<ModelType>> makeTrayRequest<ModelType>(
  TrayRequest request, {
  http.Client? client,
  FetchTrayDebugLevel? requestDebugLevel,
}) async {
  // define the client
  final theClient = client ?? http.Client();

  // get the correct caller method
  final methodCaller = getEnvironmentMethod(theClient, request.method);

  // the response
  var response = http.Response('', 200);

  try {
    // if in debug mode (at least FetchTrayDebugLevel.everything) -> log
    logRequest(
      message:
          '---------------------------------- \nStarting FetchTray Request (${request.getUrlWithParams()})',
      logType: FetchTrayLogLevel.info,
      requestDebugLevel: requestDebugLevel,
      request: request,
      response: response,
    );

    final url = Uri.parse(await request.getUrlWithParams());
    final headers = await request.getHeaders();
    final body = await request.getBody();

    // make request
    response = await methodCaller(
      url,
      headers: headers,
      body: body,
    );

    // if in debug mode (at least FetchTrayDebugLevel.everything) -> log
    logRequest(
      message: 'FetchTray Response (${request.getUrlWithParams()})',
      logType: FetchTrayLogLevel.info,
      requestDebugLevel: requestDebugLevel,
      request: request,
      response: response,
    );

    // if response successful -> parse it and return
    if (validStatuses.contains(response.statusCode)) {
      final responseJson =
          (response.body != '') ? jsonDecode(response.body) : response.body;

      try {
        final trayRequestResponse = TrayRequestResponse<ModelType>(
          data: request.getModelFromJson(
            responseJson,
          ),
          dataRaw: responseJson,
        );

        // call after success hook
        request.afterSuccess(trayRequestResponse);

        // return it
        return Future.value(trayRequestResponse);
      } catch (err) {
        // log error
        logRequest(
          message:
              'FETCH TRAY EXCEPTION: Could not convert the code to json! ${err.toString()}',
          logType: FetchTrayLogLevel.error,
          requestDebugLevel: requestDebugLevel,
          request: request,
          response: response,
        );

        final trayRequestResponse = TrayRequestResponse<ModelType>(
          error: request.getEnvironment().parseErrorDetails(
            request,
            response,
            {'rawJson': response.body},
          ),
        );
        return Future.value(trayRequestResponse);
      }
    }

    // try to parse the json anyway, so we can get a good error message
    final bodyJson = jsonDecode(response.body);

    // log error
    logRequest(
      message:
          'FETCH TRAY EXCEPTION: Api returned the status error code ${response.statusCode}',
      logType: FetchTrayLogLevel.error,
      requestDebugLevel: requestDebugLevel,
      request: request,
      response: response,
    );

    // If the server did not return a 200 OK response,
    // then throw an exception.
    return TrayRequestResponse(
      error: request.getEnvironment().parseErrorDetails(
            request,
            response,
            bodyJson,
          ),
    );
  }
  // If we got an error related to formatting -> we probably got a wrong response from server
  // either no json response, or the json doesn't match our model
  on FormatException catch (err, stackTrace) {
    // if in debug mode (at least FetchTrayDebugLevel.onlyErrors) -> allow logging
    logRequest(
      message:
          'FETCH TRAY FORMAT EXCEPTION: result could not be converted! Please check whether the result was really a json entity representing the model. (${err.toString()})',
      logType: FetchTrayLogLevel.error,
      requestDebugLevel: requestDebugLevel,
      request: request,
      response: response,
      stackTrace: stackTrace,
    );

    // return tray response with error
    return TrayRequestResponse(
      error: request.getEnvironment().parseErrorDetails(
        request,
        response,
        {
          'message': 'Unexpected server response!',
        },
        debugInfo: {
          'debugHint':
              'FetchTray result could not be converted! Please check whether the result was really a json entity representing the model. (${err.toString()})',
          'resultBody': response.body,
        },
      ),
    );
  } on Exception catch (err, stackTrace) {
    // log an error to console
    logRequest(
      message: 'FETCH TRAY EXCEPTION: ${err.toString()}',
      logType: FetchTrayLogLevel.error,
      requestDebugLevel: requestDebugLevel,
      request: request,
      response: response,
      stackTrace: stackTrace,
    );

    // If there was another exception
    // then throw an exception.
    return TrayRequestResponse(
      error: request.getEnvironment().parseErrorDetails(
        request,
        response,
        {},
        debugInfo: {
          'resultBody': response.body,
        },
      ),
    );
  }
}