intercept<BodyType> method

  1. @override
FutureOr<Response<BodyType>> intercept<BodyType>(
  1. Chain<BodyType> chain
)

Handles chopper request and creates alice http call

Implementation

@override
FutureOr<Response<BodyType>> intercept<BodyType>(
  Chain<BodyType> chain,
) async {
  final int requestId = getRequestHashCode(
    /// The alice_token header is added to the request in order to keep track
    /// of the request in the AliceCore instance.
    applyHeader(chain.request, 'alice_token', const Uuid().v4()),
  );

  aliceCore.addCall(
    AliceHttpCall(requestId)
      ..method = chain.request.method
      ..endpoint =
          chain.request.url.path.isEmpty ? '/' : chain.request.url.path
      ..server = chain.request.url.host
      ..secure = chain.request.url.scheme == 'https'
      ..uri = chain.request.url.toString()
      ..client = 'Chopper'
      ..request =
          (AliceHttpRequest()
            ..size = switch (chain.request.body) {
              dynamic body when body is String => utf8.encode(body).length,
              dynamic body when body is List<int> => body.length,
              dynamic body when body == null => 0,
              _ => utf8.encode(body.toString()).length,
            }
            ..body = chain.request.body ?? ''
            ..time = DateTime.now()
            ..headers = chain.request.headers
            ..contentType =
                chain.request.headers[HttpHeaders.contentTypeHeader] ??
                'unknown'
            ..formDataFields =
                chain.request.parts
                    .whereType<PartValue>()
                    .map(
                      (field) => AliceFormDataField(field.name, field.value),
                    )
                    .toList()
            ..formDataFiles =
                chain.request.parts
                    .whereType<PartValueFile>()
                    .map((file) => AliceFormDataFile(file.value, "", 0))
                    .toList()
            ..queryParameters = chain.request.parameters)
      ..response = AliceHttpResponse(),
  );

  try {
    final Response<BodyType> response = await chain.proceed(chain.request);

    aliceCore.addResponse(
      AliceHttpResponse()
        ..status = response.statusCode
        ..body = response.body ?? ''
        ..size = switch (response.body) {
          dynamic body when body is String => utf8.encode(body).length,
          dynamic body when body is List<int> => body.length,
          dynamic body when body == null => 0,
          _ => utf8.encode(body.toString()).length,
        }
        ..time = DateTime.now()
        ..headers = <String, String>{
          for (final MapEntry<String, String> entry
              in response.headers.entries)
            entry.key: entry.value,
        },
      requestId,
    );

    if (!response.isSuccessful || response.error != null) {
      aliceCore.addError(AliceHttpError()..error = response.error, requestId);
    }

    return response;
  } catch (error, stackTrace) {
    /// Log error to Alice log
    AliceUtils.log(error.toString());

    aliceCore.addLog(
      AliceLog(
        message: error.toString(),
        level: DiagnosticLevel.error,
        error: error,
        stackTrace: stackTrace,
      ),
    );

    /// Add empty response to Alice core
    aliceCore.addResponse(AliceHttpResponse()..status = -1, requestId);

    /// Add error to Alice core
    aliceCore.addError(
      AliceHttpError()
        ..error = error
        ..stackTrace = stackTrace,
      requestId,
    );

    /// Rethrow error
    rethrow;
  }
}