replayRequest static method

Future replayRequest(
  1. String traceId, {
  2. Map<String, String>? modifiedHeaders,
  3. dynamic modifiedBody,
  4. String? modifiedUrl,
  5. BloomHttpClient? client,
})

Replays a captured request with optional parameter overrides, re-executing it and recording a new trace.

Implementation

static Future<dynamic> replayRequest(
  String traceId, {
  Map<String, String>? modifiedHeaders,
  dynamic modifiedBody,
  String? modifiedUrl,
  BloomHttpClient? client,
}) async {
  final original = _traces.firstWhere(
    (t) => t.id == traceId,
    orElse: () => throw StateError('BloomNetworkInspector: Trace with ID "$traceId" not found.'),
  );

  final httpClient = client ?? BloomHttpClient();
  final targetUrl = modifiedUrl ?? original.url;
  final targetHeaders = {
    ...original.headers,
    if (modifiedHeaders != null) ...modifiedHeaders,
  };
  final targetBody = modifiedBody ?? original.body;

  final stopwatch = Stopwatch()..start();

  try {
    dynamic result;
    switch (original.method.toUpperCase()) {
      case 'GET':
        result = await httpClient.get<dynamic>(targetUrl, headers: targetHeaders);
        break;
      case 'POST':
        result = await httpClient.post<dynamic>(targetUrl, body: targetBody, headers: targetHeaders);
        break;
      case 'PUT':
        result = await httpClient.put<dynamic>(targetUrl, body: targetBody, headers: targetHeaders);
        break;
      case 'PATCH':
        result = await httpClient.patch<dynamic>(targetUrl, body: targetBody, headers: targetHeaders);
        break;
      case 'DELETE':
        result = await httpClient.delete<dynamic>(targetUrl, body: targetBody, headers: targetHeaders);
        break;
      default:
        result = await httpClient.get<dynamic>(targetUrl, headers: targetHeaders);
    }
    stopwatch.stop();

    // Annotate the last recorded trace from BloomHttpClient
    if (_traces.isNotEmpty) {
      final lastIdx = _traces.length - 1;
      final lastTrace = _traces[lastIdx];
      _traces[lastIdx] = BloomNetworkTrace(
        id: lastTrace.id,
        method: lastTrace.method,
        url: lastTrace.url,
        headers: lastTrace.headers,
        body: lastTrace.body,
        timestamp: lastTrace.timestamp,
        statusCode: lastTrace.statusCode,
        responseBody: lastTrace.responseBody,
        latency: lastTrace.latency,
        error: lastTrace.error,
        isReplay: true,
        originalTraceId: traceId,
      );
    }
    return result;
  } catch (e) {
    stopwatch.stop();
    if (_traces.isNotEmpty) {
      final lastIdx = _traces.length - 1;
      final lastTrace = _traces[lastIdx];
      _traces[lastIdx] = BloomNetworkTrace(
        id: lastTrace.id,
        method: lastTrace.method,
        url: lastTrace.url,
        headers: lastTrace.headers,
        body: lastTrace.body,
        timestamp: lastTrace.timestamp,
        statusCode: lastTrace.statusCode,
        responseBody: lastTrace.responseBody,
        latency: lastTrace.latency,
        error: lastTrace.error,
        isReplay: true,
        originalTraceId: traceId,
      );
    }
    rethrow;
  }
}