request method

Future<HttpResponse> request(
  1. PeerId peerId,
  2. HttpMethod method,
  3. String path, {
  4. Map<String, String>? headers,
  5. Uint8List? body,
  6. Duration? timeout,
})

Make an HTTP request to a peer

Implementation

Future<HttpResponse> request(
  PeerId peerId,
  HttpMethod method,
  String path, {
  Map<String, String>? headers,
  Uint8List? body,
  Duration? timeout,
}) async {
  final startTime = DateTime.now();
  _logger.info('πŸš€ [HTTP-REQUEST-START] Making HTTP request to peer ${peerId.toString()}: ${method.value} $path');

  // Phase 1: Stream Creation
  _logger.info('πŸ“‘ [HTTP-REQUEST-PHASE-1] Creating new stream to peer ${peerId.toString()}');
  final streamStartTime = DateTime.now();

  final stream = await host.newStream(
    peerId,
    [HttpProtocolConstants.protocolId],
    Context(),
  );

  final streamCreationTime = DateTime.now().difference(streamStartTime);
  _logger.info('βœ… [HTTP-REQUEST-PHASE-1] Stream created successfully in ${streamCreationTime.inMilliseconds}ms. Stream ID: ${stream.id}');

  try {
    // Phase 2: Stream Setup
    _logger.info('βš™οΈ [HTTP-REQUEST-PHASE-2] Setting up stream service and deadline');
    stream.scope().setService(HttpProtocolConstants.serviceName);

    final requestTimeout = timeout ?? HttpProtocolConstants.responseTimeout;
    await stream.setDeadline(DateTime.now().add(requestTimeout));
    _logger.info('βœ… [HTTP-REQUEST-PHASE-2] Stream setup completed with timeout: ${requestTimeout.inSeconds}s');

    // Phase 3: Request Creation and Serialization
    _logger.info('πŸ“ [HTTP-REQUEST-PHASE-3] Creating and serializing HTTP request');
    final requestCreateStartTime = DateTime.now();

    final request = HttpRequest(
      method: method,
      path: path,
      headers: headers ?? {},
      body: body,
      remotePeer: host.id,
    );

    final requestData = request.serialize();
    final requestCreateTime = DateTime.now().difference(requestCreateStartTime);
    _logger.info('βœ… [HTTP-REQUEST-PHASE-3] Request serialized in ${requestCreateTime.inMilliseconds}ms. Size: ${requestData.length} bytes');

    // Phase 4: Send Request
    _logger.info('πŸ“€ [HTTP-REQUEST-PHASE-4] Sending HTTP request data to stream');
    final sendStartTime = DateTime.now();

    await stream.write(requestData);

    final sendTime = DateTime.now().difference(sendStartTime);
    _logger.info('βœ… [HTTP-REQUEST-PHASE-4] Request sent successfully in ${sendTime.inMilliseconds}ms');

    // Phase 5: Read Response
    _logger.info('πŸ“₯ [HTTP-REQUEST-PHASE-5] Reading HTTP response from stream');
    final readStartTime = DateTime.now();

    final responseData = await _readHttpMessage(stream);

    final readTime = DateTime.now().difference(readStartTime);
    _logger.info('βœ… [HTTP-REQUEST-PHASE-5] Response data read in ${readTime.inMilliseconds}ms. Size: ${responseData.length} bytes');

    if (responseData.isEmpty) {
      throw Exception('Received empty response');
    }

    // Phase 6: Parse Response
    _logger.info('πŸ” [HTTP-REQUEST-PHASE-6] Parsing HTTP response');
    final parseStartTime = DateTime.now();

    final response = HttpResponse.parse(responseData);

    final parseTime = DateTime.now().difference(parseStartTime);
    final totalTime = DateTime.now().difference(startTime);
    _logger.info('βœ… [HTTP-REQUEST-PHASE-6] Response parsed in ${parseTime.inMilliseconds}ms');
    _logger.info('πŸŽ‰ [HTTP-REQUEST-COMPLETE] Total request time: ${totalTime.inMilliseconds}ms. Status: ${response.status.code} ${response.status.message}');

    return response;

  } catch (e, stackTrace) {
    final totalTime = DateTime.now().difference(startTime);
    _logger.severe('❌ [HTTP-REQUEST-ERROR] Request failed after ${totalTime.inMilliseconds}ms: $e\n$stackTrace');
    rethrow;
  } finally {
    try {
      _logger.info('πŸ”’ [HTTP-REQUEST-CLEANUP] Closing stream');
      await stream.close();
      _logger.info('βœ… [HTTP-REQUEST-CLEANUP] Stream closed successfully');
    } catch (e) {
      _logger.warning('⚠️ [HTTP-REQUEST-CLEANUP] Error closing request stream: $e');
    }
  }
}