request method
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');
}
}
}