From 8476937dbd2d45538fccc1c76b7b6f7e804eabb7 Mon Sep 17 00:00:00 2001
From: Clasherzz <govindkm20044@gmail.com>
Date: Mon, 31 Mar 2025 02:04:37 +0530
Subject: [PATCH 1/8] commiting

---
 lib/providers/collection_providers.dart       | 201 ++++++++++---
 .../details_card/response_pane.dart           | 242 +++++++++++++++-
 packages/apidash_core/lib/apidash_core.dart   |   2 +-
 packages/apidash_core/lib/consts.dart         |   1 +
 .../lib/models/http_sse_event_model.dart      |  68 +++++
 .../models/http_sse_event_model.freezed.dart  | 271 ++++++++++++++++++
 .../lib/models/http_sse_event_model.g.dart    |  27 ++
 packages/apidash_core/lib/models/models.dart  |   1 +
 .../lib/services/http_service.dart            | 127 +++++++-
 .../lib/services/http_sse_service.dart        | 113 ++++++++
 .../apidash_core/lib/services/services.dart   |   1 +
 11 files changed, 989 insertions(+), 65 deletions(-)
 create mode 100644 packages/apidash_core/lib/models/http_sse_event_model.dart
 create mode 100644 packages/apidash_core/lib/models/http_sse_event_model.freezed.dart
 create mode 100644 packages/apidash_core/lib/models/http_sse_event_model.g.dart
 create mode 100644 packages/apidash_core/lib/services/http_sse_service.dart

diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart
index 35bc4aa0c..c6b061854 100644
--- a/lib/providers/collection_providers.dart
+++ b/lib/providers/collection_providers.dart
@@ -1,3 +1,5 @@
+import 'dart:convert';
+
 import 'package:apidash_core/apidash_core.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -20,6 +22,39 @@ final selectedRequestModelProvider = StateProvider<RequestModel?>((ref) {
   }
 });
 
+class SSEFramesNotifier extends StateNotifier<Map<String, List<dynamic>>> {
+  SSEFramesNotifier() : super({});
+
+  void addFrame(String requestId, dynamic frame) {
+    state = {
+      ...state,
+      requestId: [...(state[requestId] ?? []), SSEEventModel.fromRawSSE(frame)],
+    };
+  }
+
+  void clearFrames(String requestId) {
+    if (state.containsKey(requestId)) {
+      state = {
+        ...state,
+        requestId: [],
+      };
+    }
+  }
+
+  void removeRequest(String requestId) {
+    final newState = {...state};
+    newState.remove(requestId);
+    state = newState;
+  }
+}
+
+// Provide it globally
+final sseFramesProvider =
+    StateNotifierProvider<SSEFramesNotifier, Map<String, List<dynamic>>>(
+  (ref) => SSEFramesNotifier(),
+);
+
+
 final requestSequenceProvider = StateProvider<List<String>>((ref) {
   var ids = hiveHandler.getIds();
   return ids ?? [];
@@ -289,58 +324,138 @@ class CollectionStateNotifier
     state = map;
 
     bool noSSL = ref.read(settingsProvider).isSSLDisabled;
-    var responseRec = await sendHttpRequest(
+    
+    state = map;
+    var responseRec = await sendSSERequest(
       requestId,
       apiType,
       substitutedHttpRequestModel,
       defaultUriScheme: defaultUriScheme,
       noSSL: noSSL,
-    );
-
-    late final RequestModel newRequestModel;
-    if (responseRec.$1 == null) {
-      newRequestModel = requestModel.copyWith(
-        responseStatus: -1,
-        message: responseRec.$3,
-        isWorking: false,
-      );
-    } else {
-      final httpResponseModel = baseHttpResponseModel.fromResponse(
-        response: responseRec.$1!,
-        time: responseRec.$2!,
-      );
-      int statusCode = responseRec.$1!.statusCode;
-      newRequestModel = requestModel.copyWith(
+      onConnect: (statusCode, headers) {
+        map = {...state!};
+        map[requestId] = requestModel.copyWith(
         responseStatus: statusCode,
         message: kResponseCodeReasons[statusCode],
-        httpResponseModel: httpResponseModel,
-        isWorking: false,
-      );
-      String newHistoryId = getNewUuid();
-      HistoryRequestModel model = HistoryRequestModel(
-        historyId: newHistoryId,
-        metaData: HistoryMetaModel(
-          historyId: newHistoryId,
-          requestId: requestId,
-          apiType: requestModel.apiType,
-          name: requestModel.name,
-          url: substitutedHttpRequestModel.url,
-          method: substitutedHttpRequestModel.method,
-          responseStatus: statusCode,
-          timeStamp: DateTime.now(),
-        ),
-        httpRequestModel: substitutedHttpRequestModel,
-        httpResponseModel: httpResponseModel,
+        httpResponseModel: null,
+        isWorking: true,
       );
-      ref.read(historyMetaStateNotifier.notifier).addHistoryRequest(model);
-    }
-
-    // update state with response data
-    map = {...state!};
-    map[requestId] = newRequestModel;
-    state = map;
+      
+       
+      },
+      onData: (response) {
+          ref.read(sseFramesProvider.notifier).addFrame(requestId, response);
+      },
+    );
 
-    unsave();
+    late final RequestModel newRequestModel;
+  //   if (responseRec.$1 == null && responseRec.$4 == null) {
+  //     print("inside first if");
+      
+  //     newRequestModel = requestModel.copyWith(
+  //       responseStatus: -1,
+  //       message: responseRec.$3,
+  //       isWorking: false,
+  //     );
+  //   } else if(responseRec.$1 != null){
+  //      print("inside second if");
+  //     final httpResponseModel = baseHttpResponseModel.fromResponse(
+  //       response: responseRec.$1!,
+  //       time: responseRec.$2!,
+  //     );
+  // //     if(responseRec.$1!.headers['content-type']?.contains('text/event-stream') ?? false){
+        
+  // //       Stream.value(responseRec.$1!.bodyBytes  as List<int>).byteStream.transform(utf8.decoder).transform(const LineSplitter());
+
+  // //   await for (final event in utf8Stream) {
+  // //     if (event.isNotEmpty) {
+  // //       yield SSEEventModel.fromRawSSE(event);  // ✅ Emit each event lazily
+  // //     }
+  // //   }
+  // // }
+  //     // }
+  //     int statusCode = responseRec.$1!.statusCode;
+  //     newRequestModel = requestModel.copyWith(
+  //       responseStatus: statusCode,
+  //       message: kResponseCodeReasons[statusCode],
+  //       httpResponseModel: httpResponseModel,
+  //       isWorking: false,
+  //     );
+  //     String newHistoryId = getNewUuid();
+  //     HistoryRequestModel model = HistoryRequestModel(
+  //       historyId: newHistoryId,
+  //       metaData: HistoryMetaModel(
+  //         historyId: newHistoryId,
+  //         requestId: requestId,
+  //         apiType: requestModel.apiType,
+  //         name: requestModel.name,
+  //         url: substitutedHttpRequestModel.url,
+  //         method: substitutedHttpRequestModel.method,
+  //         responseStatus: statusCode,
+  //         timeStamp: DateTime.now(),
+  //       ),
+  //       httpRequestModel: substitutedHttpRequestModel,
+  //       httpResponseModel: httpResponseModel,
+  //     );
+  //     ref.read(historyMetaStateNotifier.notifier).addHistoryRequest(model);
+  //   }else if(responseRec.$4 != null){
+  //     print("inside else if");
+      
+  //     // final httpResponseModel = baseHttpResponseModel.fromResponse(
+  //     //   response: responseRec.$4!,
+  //     //   time: responseRec.$2!,
+  //     // );
+  // //     if(responseRec.$1!.headers['content-type']?.contains('text/event-stream') ?? false){
+        
+  // //       Stream.value(responseRec.$1!.bodyBytes  as List<int>).byteStream.transform(utf8.decoder).transform(const LineSplitter());
+
+  // //   await for (final event in utf8Stream) {
+  // //     if (event.isNotEmpty) {
+  // //       yield SSEEventModel.fromRawSSE(event);  // ✅ Emit each event lazily
+  // //     }
+  // //   }
+  // // }
+  //     // }
+  // //    var streamedResponse = responseRec.$4!;
+  // //    final stream = streamedResponse.stream
+  // //     .transform(utf8.decoder)
+  // //     .transform(const LineSplitter());
+
+  // // stream.listen(
+  // //   (event) {
+  // //     if (event.isNotEmpty) {
+  // //       print('🔹 SSE Event Received: $event');
+  // //       print(event.toString());
+  // //       // final parsedEvent = SSEEventModel.fromRawSSE(event);
+  // //       // ref.read(sseFramesProvider.notifier).addFrame(requestId, parsedEvent);
+       
+  // //     }
+  // //   },
+  // //   onError: (error) {
+  // //     // ref.read(sseFramesProvider.notifier).update((state) {
+  // //     //   return {...state, requestId: [...(state[requestId] ?? []), 'Error: $error']};
+  // //     // });
+  // //     // finalizeRequestModel(requestId);
+  // //   },
+  // //   onDone: () {
+  // //  //   finalizeRequestModel(requestId);
+  // //   },
+  // // );
+
+  // // // newRequestModel = requestModel.copyWith(
+  // // //       responseStatus: 200,
+  // // //       message: kResponseCodeReasons[200],
+  // //       httpResponseModel: httpResponseModel,
+  // //       isWorking: false,
+  // //     );
+  //   }
+
+  //   // update state with response data
+  //   // map = {...state!};
+  //   // map[requestId] = newRequestModel;
+  //   // state = map;
+
+  //   unsave();
   }
 
   void cancelRequest() {
diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
index 367bb4128..ab4350f60 100644
--- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart
+++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
@@ -1,3 +1,5 @@
+import 'dart:convert';
+
 import 'package:apidash_core/apidash_core.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_riverpod/flutter_riverpod.dart';
@@ -5,11 +7,12 @@ import 'package:apidash/providers/providers.dart';
 import 'package:apidash/widgets/widgets.dart';
 import 'package:apidash/consts.dart';
 
-class ResponsePane extends ConsumerWidget {
+class ResponsePane extends ConsumerWidget{
   const ResponsePane({super.key});
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
+    final selectedId = ref.watch(selectedIdStateProvider)!;
     final isWorking = ref.watch(
             selectedRequestModelProvider.select((value) => value?.isWorking)) ??
         false;
@@ -19,16 +22,20 @@ class ResponsePane extends ConsumerWidget {
         selectedRequestModelProvider.select((value) => value?.responseStatus));
     final message = ref
         .watch(selectedRequestModelProvider.select((value) => value?.message));
+    final sseFramesNotifier =  ref.watch(sseFramesProvider.select((state) => state[selectedId] ?? []));
 
-    if (isWorking) {
+    
+    if (isWorking && sseFramesNotifier.isEmpty) {
       return SendingWidget(
         startSendingTime: startSendingTime,
       );
+
     }
-    if (responseStatus == null) {
+
+    if (responseStatus == null && sseFramesNotifier.isEmpty) {
       return const NotSentWidget();
     }
-    if (responseStatus == -1) {
+    if (responseStatus == -1 && sseFramesNotifier.isEmpty) {
       return message == kMsgRequestCancelled
           ? ErrorMessage(
               message: message,
@@ -54,7 +61,6 @@ class ResponseDetails extends ConsumerWidget {
         .watch(selectedRequestModelProvider.select((value) => value?.message));
     final responseModel = ref.watch(selectedRequestModelProvider
         .select((value) => value?.httpResponseModel));
-
     return Column(
       children: [
         ResponsePaneHeader(
@@ -78,12 +84,22 @@ class ResponseTabs extends ConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final selectedId = ref.watch(selectedIdStateProvider);
+    final selectedId = ref.watch(selectedIdStateProvider)!;
+    final apiType = ref
+        .watch(selectedRequestModelProvider.select((value) => value?.apiType));
+
     return ResponseTabView(
       selectedId: selectedId,
-      children: const [
-        ResponseBodyTab(),
-        ResponseHeadersTab(),
+      children: [
+        if (apiType == APIType.rest || apiType == APIType.graphql) ...[
+          SSEView(requestId: selectedId ),  
+        const ResponseHeadersTab(),
+        ]
+        // ] else if (apiType == APIType.rest) ...const [
+        //   WebsocketResponseView(),
+        //   ResponseHeadersTab(),
+        // ],
+      
       ],
     );
   }
@@ -106,15 +122,211 @@ class ResponseHeadersTab extends ConsumerWidget {
 
   @override
   Widget build(BuildContext context, WidgetRef ref) {
-    final requestHeaders = ref.watch(selectedRequestModelProvider
+    final requestHttpHeaders = ref.watch(selectedRequestModelProvider
             .select((value) => value?.httpResponseModel?.requestHeaders)) ??
         {};
-    final responseHeaders = ref.watch(selectedRequestModelProvider
+    final responseHttpHeaders = ref.watch(selectedRequestModelProvider
             .select((value) => value?.httpResponseModel?.headers)) ??
         {};
-    return ResponseHeaders(
-      responseHeaders: responseHeaders,
-      requestHeaders: requestHeaders,
-    );
+    // final requestWebSocketHeaders = ref.watch(selectedRequestModelProvider
+    //         .select((value) => value?.webSocketResponseModel?.requestHeaders)) ??
+    //     {};
+    // final responseWebSocketHeaders = ref.watch(selectedRequestModelProvider
+    //         .select((value) => value?.webSocketResponseModel?.headers)) ??
+    //     {};
+    final apiType = ref
+        .watch(selectedRequestModelProvider.select((value) => value?.apiType));
+    switch (apiType!) {
+      // case APIType.rest || APIType.graphql:
+      //   return ResponseHeaders(
+      //     responseHeaders: responseHttpHeaders,
+      //     requestHeaders: requestHttpHeaders,
+      //   );
+      case APIType.rest:
+        return ResponseHeaders(
+          responseHeaders: responseHttpHeaders,
+          requestHeaders: requestHttpHeaders,
+        );
+      case _:
+        return ResponseHeaders(
+          responseHeaders: responseHttpHeaders,
+          requestHeaders: requestHttpHeaders,
+        );
+    }
+      
   }
 }
+
+
+
+class SSEView extends ConsumerStatefulWidget {
+  final String requestId;
+  const SSEView({super.key, required this.requestId});
+
+  @override
+  ConsumerState<SSEView> createState() => _SSEViewState();
+}
+
+class _SSEViewState extends ConsumerState<SSEView> {
+  final ScrollController _controller = ScrollController();
+  bool _isAtBottom = true;
+  List<SSEEventModel> _pausedFrames = [];
+
+  @override
+  void initState() {
+    super.initState();
+
+    _controller.addListener(() {
+      if (_controller.hasClients) {
+        final isAtBottom = _controller.position.pixels >= _controller.position.maxScrollExtent;
+        setState(() {
+          _isAtBottom = isAtBottom;
+        });
+      }
+    });
+  }
+
+  @override
+  void dispose() {
+    _controller.dispose();
+    super.dispose();
+  }
+
+  @override
+  Widget build(BuildContext context) {
+    final frames = ref.watch(sseFramesProvider.select((state) => state[widget.requestId] ?? []));
+
+    if (_isAtBottom) {
+      _pausedFrames = List.from(frames);
+    }
+    final displayFrames = _isAtBottom ? frames : _pausedFrames;
+
+    return Scaffold(
+      appBar: AppBar(title: Text("SSE Stream - ${widget.requestId}")),
+      body: Column(
+        children: [
+          Expanded(
+            child: ListView.builder(
+              controller: _controller,
+              itemCount: displayFrames.length,
+              itemBuilder: (context, index) {
+                final event = displayFrames[displayFrames.length - index - 1];
+
+                return Padding(
+                  padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
+                  child: Card(
+                    elevation: 2,
+                    shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)),
+                    child: Padding(
+                      padding: const EdgeInsets.all(8),
+                      child: Column(
+                        crossAxisAlignment: CrossAxisAlignment.start,
+                        children: [
+                          if (event.event.isEmpty) _buildTag("Event", "message", Colors.blue),
+                          _buildData(event.data),
+                          if (event.id != null && event.id!.isNotEmpty) _buildTag("ID", event.id!, Colors.orange),
+                          if (event.retry != null) _buildTag("Retry", "${event.retry} ms", Colors.purple),
+                          if (event.customFields != null && event.customFields!.isNotEmpty)
+                            ...event.customFields!.entries.map(
+                              (e) => _buildTag(e.key, e.value, Colors.grey),
+                            ),
+                        ],
+                      ),
+                    ),
+                  ),
+                );
+              },
+            ),
+          ),
+          if (!_isAtBottom)
+            ElevatedButton(
+              onPressed: () {
+                _controller.animateTo(
+                  _controller.position.maxScrollExtent,
+                  duration: const Duration(milliseconds: 500),
+                  curve: Curves.easeOut,
+                );
+              },
+              child: const Text("Scroll to Bottom"),
+            ),
+        ],
+      ),
+    );
+  }
+
+  Widget _buildTag(String title, String value, Color color) {
+    return Column(
+      crossAxisAlignment: CrossAxisAlignment.start,
+      children: [
+        Padding(
+          padding: const EdgeInsets.only(bottom: 4),
+          child: Row(
+            children: [
+              Container(
+                padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
+                decoration: BoxDecoration(
+                  color: color.withOpacity(0.2),
+                  borderRadius: BorderRadius.circular(4),
+                ),
+                child: Text(
+                  title,
+                  style: TextStyle(color: color, fontWeight: FontWeight.bold),
+                ),
+              ),
+              const SizedBox(width: 8),
+              Expanded(child: Text(value, style: const TextStyle(fontSize: 14))),
+            ],
+          ),
+        ),
+        const Divider(height: 10, thickness: 0.5), // Add a subtle separator line
+      ],
+    );
+  }
+
+  Widget _buildData(String data) {
+    bool _isExpanded = false;
+
+    return StatefulBuilder(
+      builder: (context, setState) {
+        try {
+          final jsonData = json.decode(data);
+          final formattedJson = const JsonEncoder.withIndent('  ').convert(jsonData);
+          final bool shouldCollapse = formattedJson.length > 2;
+
+          return Column(
+            crossAxisAlignment: CrossAxisAlignment.start,
+            children: [
+              Row(
+                children: [
+                  Text("Data", style: const TextStyle(fontSize: 12, fontWeight: FontWeight.bold, color: Colors.green)),
+                  const Spacer(),
+                  if (shouldCollapse)
+                    IconButton(
+                      icon: Icon(_isExpanded ? Icons.expand_less : Icons.expand_more),
+                      onPressed: () => setState(() => _isExpanded = !_isExpanded),
+                      iconSize: 18,
+                    ),
+                ],
+              ),
+              Container(
+                padding: const EdgeInsets.all(8),
+                margin: const EdgeInsets.only(top: 4),
+                decoration: BoxDecoration(
+                  color: Colors.black.withOpacity(0.05),
+                  borderRadius: BorderRadius.circular(6),
+                ),
+                child: Text(
+                  _isExpanded || !shouldCollapse ? formattedJson : "${formattedJson.substring(0, 100)}...",
+                  style: const TextStyle(fontFamily: 'Courier', fontSize: 12),
+                ),
+              ),
+              const Divider(height: 10, thickness: 0.5),
+            ],
+          );
+        } catch (_) {
+          return _buildTag("Data", data, Colors.green);
+        }
+      },
+    );
+  }
+}
\ No newline at end of file
diff --git a/packages/apidash_core/lib/apidash_core.dart b/packages/apidash_core/lib/apidash_core.dart
index 305bb5c81..a26b11b8f 100644
--- a/packages/apidash_core/lib/apidash_core.dart
+++ b/packages/apidash_core/lib/apidash_core.dart
@@ -4,7 +4,7 @@ export 'consts.dart';
 export 'extensions/extensions.dart';
 export 'models/models.dart';
 export 'utils/utils.dart';
-export 'services/services.dart';
+export 'services/services.dart' hide StreamedResponse;
 export 'import_export/import_export.dart';
 
 // Export 3rd party packages
diff --git a/packages/apidash_core/lib/consts.dart b/packages/apidash_core/lib/consts.dart
index 1d7044c74..26a24879d 100644
--- a/packages/apidash_core/lib/consts.dart
+++ b/packages/apidash_core/lib/consts.dart
@@ -3,6 +3,7 @@ import 'dart:convert';
 enum APIType {
   rest("HTTP", "HTTP"),
   graphql("GraphQL", "GQL");
+//  sse("SSE", "SSE");
 
   const APIType(this.label, this.abbr);
   final String label;
diff --git a/packages/apidash_core/lib/models/http_sse_event_model.dart b/packages/apidash_core/lib/models/http_sse_event_model.dart
new file mode 100644
index 000000000..64aa58a3e
--- /dev/null
+++ b/packages/apidash_core/lib/models/http_sse_event_model.dart
@@ -0,0 +1,68 @@
+import 'dart:convert';
+import 'package:freezed_annotation/freezed_annotation.dart';
+
+part 'http_sse_event_model.freezed.dart';
+part 'http_sse_event_model.g.dart';
+
+@freezed
+class SSEEventModel with _$SSEEventModel {
+  const SSEEventModel._();
+
+  @JsonSerializable(
+    explicitToJson: true,
+    anyMap: true,
+  )
+  const factory SSEEventModel({
+    @Default("") String event, // Custom event name
+    @Default("") String data, // Event data (main payload)
+    String? id, // Last event ID for reconnection
+    int? retry, // Reconnect interval in milliseconds
+    Map<String, String>? customFields, // Additional metadata
+  }) = _SSEEventModel;
+
+  factory SSEEventModel.fromJson(Map<String, Object?> json) =>
+      _$SSEEventModelFromJson(json);
+
+  /// Parses raw SSE data into an SSEEventModel
+  static SSEEventModel fromRawSSE(String rawEvent) {
+    final Map<String, String> fields = {};
+    String? event, data, id;
+    int? retry;
+
+    for (var line in LineSplitter.split(rawEvent)) {
+      if (line.startsWith(":")) {
+        continue; // Ignore comments
+      }
+      final parts = line.split(": ");
+      if (parts.length < 2) continue;
+
+      final key = parts[0].trim();
+      final value = parts.sublist(1).join(": ").trim();
+
+      switch (key) {
+        case "event":
+          event = value;
+          break;
+        case "data":
+          data = (data ?? "") + value + "\n"; // Multi-line data support
+          break;
+        case "id":
+          id = value;
+          break;
+        case "retry":
+          retry = int.tryParse(value);
+          break;
+        default:
+          fields[key] = value; // Store unknown fields as custom metadata
+      }
+    }
+
+    return SSEEventModel(
+      event: event ?? "",
+      data: data?.trim() ?? "",
+      id: id,
+      retry: retry,
+      customFields: fields.isNotEmpty ? fields : null,
+    );
+  }
+}
\ No newline at end of file
diff --git a/packages/apidash_core/lib/models/http_sse_event_model.freezed.dart b/packages/apidash_core/lib/models/http_sse_event_model.freezed.dart
new file mode 100644
index 000000000..d35f2c256
--- /dev/null
+++ b/packages/apidash_core/lib/models/http_sse_event_model.freezed.dart
@@ -0,0 +1,271 @@
+// coverage:ignore-file
+// GENERATED CODE - DO NOT MODIFY BY HAND
+// ignore_for_file: type=lint
+// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
+
+part of 'http_sse_event_model.dart';
+
+// **************************************************************************
+// FreezedGenerator
+// **************************************************************************
+
+T _$identity<T>(T value) => value;
+
+final _privateConstructorUsedError = UnsupportedError(
+    'It seems like you constructed your class using `MyClass._()`. This constructor is only meant to be used by freezed and you are not supposed to need it nor use it.\nPlease check the documentation here for more information: https://github.com/rrousselGit/freezed#adding-getters-and-methods-to-our-models');
+
+SSEEventModel _$SSEEventModelFromJson(Map<String, dynamic> json) {
+  return _SSEEventModel.fromJson(json);
+}
+
+/// @nodoc
+mixin _$SSEEventModel {
+  String get event => throw _privateConstructorUsedError; // Custom event name
+  String get data =>
+      throw _privateConstructorUsedError; // Event data (main payload)
+  String? get id =>
+      throw _privateConstructorUsedError; // Last event ID for reconnection
+  int? get retry =>
+      throw _privateConstructorUsedError; // Reconnect interval in milliseconds
+  Map<String, String>? get customFields => throw _privateConstructorUsedError;
+
+  /// Serializes this SSEEventModel to a JSON map.
+  Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
+
+  /// Create a copy of SSEEventModel
+  /// with the given fields replaced by the non-null parameter values.
+  @JsonKey(includeFromJson: false, includeToJson: false)
+  $SSEEventModelCopyWith<SSEEventModel> get copyWith =>
+      throw _privateConstructorUsedError;
+}
+
+/// @nodoc
+abstract class $SSEEventModelCopyWith<$Res> {
+  factory $SSEEventModelCopyWith(
+          SSEEventModel value, $Res Function(SSEEventModel) then) =
+      _$SSEEventModelCopyWithImpl<$Res, SSEEventModel>;
+  @useResult
+  $Res call(
+      {String event,
+      String data,
+      String? id,
+      int? retry,
+      Map<String, String>? customFields});
+}
+
+/// @nodoc
+class _$SSEEventModelCopyWithImpl<$Res, $Val extends SSEEventModel>
+    implements $SSEEventModelCopyWith<$Res> {
+  _$SSEEventModelCopyWithImpl(this._value, this._then);
+
+  // ignore: unused_field
+  final $Val _value;
+  // ignore: unused_field
+  final $Res Function($Val) _then;
+
+  /// Create a copy of SSEEventModel
+  /// with the given fields replaced by the non-null parameter values.
+  @pragma('vm:prefer-inline')
+  @override
+  $Res call({
+    Object? event = null,
+    Object? data = null,
+    Object? id = freezed,
+    Object? retry = freezed,
+    Object? customFields = freezed,
+  }) {
+    return _then(_value.copyWith(
+      event: null == event
+          ? _value.event
+          : event // ignore: cast_nullable_to_non_nullable
+              as String,
+      data: null == data
+          ? _value.data
+          : data // ignore: cast_nullable_to_non_nullable
+              as String,
+      id: freezed == id
+          ? _value.id
+          : id // ignore: cast_nullable_to_non_nullable
+              as String?,
+      retry: freezed == retry
+          ? _value.retry
+          : retry // ignore: cast_nullable_to_non_nullable
+              as int?,
+      customFields: freezed == customFields
+          ? _value.customFields
+          : customFields // ignore: cast_nullable_to_non_nullable
+              as Map<String, String>?,
+    ) as $Val);
+  }
+}
+
+/// @nodoc
+abstract class _$$SSEEventModelImplCopyWith<$Res>
+    implements $SSEEventModelCopyWith<$Res> {
+  factory _$$SSEEventModelImplCopyWith(
+          _$SSEEventModelImpl value, $Res Function(_$SSEEventModelImpl) then) =
+      __$$SSEEventModelImplCopyWithImpl<$Res>;
+  @override
+  @useResult
+  $Res call(
+      {String event,
+      String data,
+      String? id,
+      int? retry,
+      Map<String, String>? customFields});
+}
+
+/// @nodoc
+class __$$SSEEventModelImplCopyWithImpl<$Res>
+    extends _$SSEEventModelCopyWithImpl<$Res, _$SSEEventModelImpl>
+    implements _$$SSEEventModelImplCopyWith<$Res> {
+  __$$SSEEventModelImplCopyWithImpl(
+      _$SSEEventModelImpl _value, $Res Function(_$SSEEventModelImpl) _then)
+      : super(_value, _then);
+
+  /// Create a copy of SSEEventModel
+  /// with the given fields replaced by the non-null parameter values.
+  @pragma('vm:prefer-inline')
+  @override
+  $Res call({
+    Object? event = null,
+    Object? data = null,
+    Object? id = freezed,
+    Object? retry = freezed,
+    Object? customFields = freezed,
+  }) {
+    return _then(_$SSEEventModelImpl(
+      event: null == event
+          ? _value.event
+          : event // ignore: cast_nullable_to_non_nullable
+              as String,
+      data: null == data
+          ? _value.data
+          : data // ignore: cast_nullable_to_non_nullable
+              as String,
+      id: freezed == id
+          ? _value.id
+          : id // ignore: cast_nullable_to_non_nullable
+              as String?,
+      retry: freezed == retry
+          ? _value.retry
+          : retry // ignore: cast_nullable_to_non_nullable
+              as int?,
+      customFields: freezed == customFields
+          ? _value._customFields
+          : customFields // ignore: cast_nullable_to_non_nullable
+              as Map<String, String>?,
+    ));
+  }
+}
+
+/// @nodoc
+
+@JsonSerializable(explicitToJson: true, anyMap: true)
+class _$SSEEventModelImpl extends _SSEEventModel {
+  const _$SSEEventModelImpl(
+      {this.event = "",
+      this.data = "",
+      this.id,
+      this.retry,
+      final Map<String, String>? customFields})
+      : _customFields = customFields,
+        super._();
+
+  factory _$SSEEventModelImpl.fromJson(Map<String, dynamic> json) =>
+      _$$SSEEventModelImplFromJson(json);
+
+  @override
+  @JsonKey()
+  final String event;
+// Custom event name
+  @override
+  @JsonKey()
+  final String data;
+// Event data (main payload)
+  @override
+  final String? id;
+// Last event ID for reconnection
+  @override
+  final int? retry;
+// Reconnect interval in milliseconds
+  final Map<String, String>? _customFields;
+// Reconnect interval in milliseconds
+  @override
+  Map<String, String>? get customFields {
+    final value = _customFields;
+    if (value == null) return null;
+    if (_customFields is EqualUnmodifiableMapView) return _customFields;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableMapView(value);
+  }
+
+  @override
+  String toString() {
+    return 'SSEEventModel(event: $event, data: $data, id: $id, retry: $retry, customFields: $customFields)';
+  }
+
+  @override
+  bool operator ==(Object other) {
+    return identical(this, other) ||
+        (other.runtimeType == runtimeType &&
+            other is _$SSEEventModelImpl &&
+            (identical(other.event, event) || other.event == event) &&
+            (identical(other.data, data) || other.data == data) &&
+            (identical(other.id, id) || other.id == id) &&
+            (identical(other.retry, retry) || other.retry == retry) &&
+            const DeepCollectionEquality()
+                .equals(other._customFields, _customFields));
+  }
+
+  @JsonKey(includeFromJson: false, includeToJson: false)
+  @override
+  int get hashCode => Object.hash(runtimeType, event, data, id, retry,
+      const DeepCollectionEquality().hash(_customFields));
+
+  /// Create a copy of SSEEventModel
+  /// with the given fields replaced by the non-null parameter values.
+  @JsonKey(includeFromJson: false, includeToJson: false)
+  @override
+  @pragma('vm:prefer-inline')
+  _$$SSEEventModelImplCopyWith<_$SSEEventModelImpl> get copyWith =>
+      __$$SSEEventModelImplCopyWithImpl<_$SSEEventModelImpl>(this, _$identity);
+
+  @override
+  Map<String, dynamic> toJson() {
+    return _$$SSEEventModelImplToJson(
+      this,
+    );
+  }
+}
+
+abstract class _SSEEventModel extends SSEEventModel {
+  const factory _SSEEventModel(
+      {final String event,
+      final String data,
+      final String? id,
+      final int? retry,
+      final Map<String, String>? customFields}) = _$SSEEventModelImpl;
+  const _SSEEventModel._() : super._();
+
+  factory _SSEEventModel.fromJson(Map<String, dynamic> json) =
+      _$SSEEventModelImpl.fromJson;
+
+  @override
+  String get event; // Custom event name
+  @override
+  String get data; // Event data (main payload)
+  @override
+  String? get id; // Last event ID for reconnection
+  @override
+  int? get retry; // Reconnect interval in milliseconds
+  @override
+  Map<String, String>? get customFields;
+
+  /// Create a copy of SSEEventModel
+  /// with the given fields replaced by the non-null parameter values.
+  @override
+  @JsonKey(includeFromJson: false, includeToJson: false)
+  _$$SSEEventModelImplCopyWith<_$SSEEventModelImpl> get copyWith =>
+      throw _privateConstructorUsedError;
+}
diff --git a/packages/apidash_core/lib/models/http_sse_event_model.g.dart b/packages/apidash_core/lib/models/http_sse_event_model.g.dart
new file mode 100644
index 000000000..b85ec871d
--- /dev/null
+++ b/packages/apidash_core/lib/models/http_sse_event_model.g.dart
@@ -0,0 +1,27 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of 'http_sse_event_model.dart';
+
+// **************************************************************************
+// JsonSerializableGenerator
+// **************************************************************************
+
+_$SSEEventModelImpl _$$SSEEventModelImplFromJson(Map json) =>
+    _$SSEEventModelImpl(
+      event: json['event'] as String? ?? "",
+      data: json['data'] as String? ?? "",
+      id: json['id'] as String?,
+      retry: (json['retry'] as num?)?.toInt(),
+      customFields: (json['customFields'] as Map?)?.map(
+        (k, e) => MapEntry(k as String, e as String),
+      ),
+    );
+
+Map<String, dynamic> _$$SSEEventModelImplToJson(_$SSEEventModelImpl instance) =>
+    <String, dynamic>{
+      'event': instance.event,
+      'data': instance.data,
+      'id': instance.id,
+      'retry': instance.retry,
+      'customFields': instance.customFields,
+    };
diff --git a/packages/apidash_core/lib/models/models.dart b/packages/apidash_core/lib/models/models.dart
index c50ec988f..71dda0ae9 100644
--- a/packages/apidash_core/lib/models/models.dart
+++ b/packages/apidash_core/lib/models/models.dart
@@ -1,3 +1,4 @@
 export 'environment_model.dart';
 export 'http_request_model.dart';
 export 'http_response_model.dart';
+export 'http_sse_event_model.dart';
\ No newline at end of file
diff --git a/packages/apidash_core/lib/services/http_service.dart b/packages/apidash_core/lib/services/http_service.dart
index ad06a21d4..4457ebafb 100644
--- a/packages/apidash_core/lib/services/http_service.dart
+++ b/packages/apidash_core/lib/services/http_service.dart
@@ -9,15 +9,19 @@ import '../utils/utils.dart';
 import 'http_client_manager.dart';
 
 typedef HttpResponse = http.Response;
+typedef StreamedResponse = http.StreamedResponse;
 
 final httpClientManager = HttpClientManager();
 
-Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
+Future<(HttpResponse?, Duration?, String?,StreamedResponse?)> sendHttpRequest(
   String requestId,
   APIType apiType,
   HttpRequestModel requestModel, {
   SupportedUriSchemes defaultUriScheme = kDefaultUriScheme,
   bool noSSL = false,
+  Function(String event)? onData,
+  Function(Object error, StackTrace stackTrace)? onError,
+  Function()? onDone,
 }) async {
   final client = httpClientManager.createClient(requestId, noSSL: noSSL);
 
@@ -35,6 +39,78 @@ Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
     try {
       Stopwatch stopwatch = Stopwatch()..start();
       if (apiType == APIType.rest) {
+        print("inside sse http serviec");
+        // ✅ SSE Handling (POST, PUT, etc. with Body)
+        var request = http.Request(requestModel.method.name.toUpperCase(), requestUrl);
+        
+        request.headers.addAll(headers);
+        request.headers["Accept"] = "text/event-stream";
+      request.headers["Cache-Control"] = "no-cache";
+      request.headers["Connection"] = "keep-alive";
+     
+        if (body != null) request.body = body;
+
+        http.StreamedResponse streamedResponse = await client.send(request);
+        print("inside streamed response");
+        final stream = streamedResponse.stream
+      .transform(utf8.decoder)
+      .transform(const LineSplitter());
+        try{ stream.listen(
+    (event) {
+      onData?.call(event);
+      if (event.isNotEmpty) {
+        print('🔹 SSE Event Received: $event');
+        print(event.toString());
+      //   final parsedEvent = SSEEventModel.fromRawSSE(event);
+      //   ref.read(sseFramesProvider.notifier).addFrame(requestId, parsedEvent);
+       
+      }
+    },
+    onError: (error) {
+      (error, stackTrace) => onError?.call(error, stackTrace);
+      print('🔹 SSE Error: $error');
+      // ref.read(sseFramesProvider.notifier).update((state) {
+      //   return {...state, requestId: [...(state[requestId] ?? []), 'Error: $error']};
+      // });
+      // finalizeRequestModel(requestId);
+    },
+    onDone: () {
+      onDone?.call();
+       print('🔹 SSE Stream Done');
+   //   finalizeRequestModel(requestId);
+    },
+ );}catch (e, stackTrace) {
+      print('🔹 Error connecting to SSE: $e');
+      onError?.call(e, stackTrace);
+      //_reconnect(onData, onError, onDone);
+    }
+      //   print("streamedResponse"+streamedResponse.headers.toString());
+      //  // var buffer = await convertStreamedResponse(streamedResponse);
+      //  // print(buffer.body.toString());
+      //   if(streamedResponse.headers['content-type']?.contains('text/event-stream') == true){
+      //     print("has the content type");
+      //   }
+      //   stopwatch.stop();
+      //   Stream<String>? utf8Stream;
+      //   if (streamedResponse.statusCode == 200) {
+         
+      //     utf8Stream = await streamedResponse.stream
+      //         .transform(utf8.decoder)
+      //         .transform(const LineSplitter());
+      //     print("utf8stream"+utf8Stream.toString());
+
+      //     await for (final event in utf8Stream) {
+      //       print("inside eventloop");
+      //       if (event.isNotEmpty) {
+      //         print('🔹 SSE Event Received: $event');
+      //       }
+      //     }
+      //   }
+      //   print("just before return ing null");
+        return (null, stopwatch.elapsed, null,streamedResponse);
+      }
+      if (apiType == APIType.rest) {
+        print("iside second rest");
         var isMultiPartRequest =
             requestModel.bodyContentType == ContentType.formdata;
 
@@ -75,7 +151,7 @@ Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
             stopwatch.stop();
             http.Response convertedMultiPartResponse =
                 await convertStreamedResponse(multiPartResponse);
-            return (convertedMultiPartResponse, stopwatch.elapsed, null);
+            return (convertedMultiPartResponse, stopwatch.elapsed, null,null);
           }
         }
         switch (requestModel.method) {
@@ -122,20 +198,59 @@ Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
         );
       }
       stopwatch.stop();
-      return (response, stopwatch.elapsed, null);
+      return (response, stopwatch.elapsed, null,null);
     } catch (e) {
+      print("inside catch");
       if (httpClientManager.wasRequestCancelled(requestId)) {
-        return (null, null, kMsgRequestCancelled);
+        return (null, null, kMsgRequestCancelled,null);
       }
-      return (null, null, e.toString());
+      return (null, null, e.toString(),null);
     } finally {
+      print("inside finallyy");
       httpClientManager.closeClient(requestId);
     }
   } else {
-    return (null, null, uriRec.$2);
+    return (null, null, uriRec.$2,null);
   }
 }
 
 void cancelHttpRequest(String? requestId) {
   httpClientManager.cancelRequest(requestId);
 }
+
+
+// void startSSE() async {
+//   var url = Uri.parse('https://sse.dev/test');
+//   var client = HttpClient();
+
+//   try {
+//     var request = await client.getUrl(url);
+    
+
+//     var response = await request.close();
+
+//     // Ensure it's a successful SSE connection
+//     if (response.statusCode == 200) {
+//       print("✅ Connected to SSE stream");
+
+//       response.transform(utf8.decoder).listen(
+//         (data) {
+//           print("🔹 SSE Event Received: $data");
+//         },
+//         onError: (error) {
+//           print("❌ SSE Error: $error");
+//         },
+//         onDone: () {
+//           print("🔌 SSE Stream Closed");
+//         },
+//         cancelOnError: true,
+//       );
+//     } else {
+//       print("❌ Failed to connect: ${response.statusCode}");
+//     }
+//   } catch (e) {
+//     print("❌ Exception: $e");
+//   }
+// }
+
+
diff --git a/packages/apidash_core/lib/services/http_sse_service.dart b/packages/apidash_core/lib/services/http_sse_service.dart
new file mode 100644
index 000000000..3a0b9777d
--- /dev/null
+++ b/packages/apidash_core/lib/services/http_sse_service.dart
@@ -0,0 +1,113 @@
+import 'dart:async';
+import 'dart:convert';
+import 'package:http/http.dart' as http;
+import '../consts.dart';
+import '../models/models.dart';
+import '../utils/utils.dart';
+import 'http_service.dart';
+
+
+Future<void> sendSSERequest(
+  String requestId,
+  APIType apiType,
+  HttpRequestModel requestModel, {
+  SupportedUriSchemes defaultUriScheme = kDefaultUriScheme,
+  bool noSSL = false,
+  Function(int statusCode, Map<String, String> headers)? onConnect,
+  Function(String event)? onData,
+  Function(Object error, StackTrace stackTrace)? onError,
+  Function()? onDone,
+}) async {
+  final client = httpClientManager.createClient(requestId, noSSL: noSSL);
+
+  (Uri?, String?) uriRec = getValidRequestUri(
+    requestModel.url,
+    requestModel.enabledParams,
+    defaultUriScheme: defaultUriScheme,
+  );
+
+  if (uriRec.$1 != null) {
+    Uri requestUrl = uriRec.$1!;
+    Map<String, String> headers = requestModel.enabledHeadersMap;
+    HttpResponse? response;
+    String? body;
+   
+      Stopwatch stopwatch = Stopwatch()..start();
+      if (apiType == APIType.rest) {
+        print("inside sse http serviec");
+        // ✅ SSE Handling (POST, PUT, etc. with Body)
+        var request = http.Request(requestModel.method.name.toUpperCase(), requestUrl);
+        
+        request.headers.addAll(headers);
+        request.headers["Accept"] = "text/event-stream";
+      request.headers["Cache-Control"] = "no-cache";
+      request.headers["Connection"] = "keep-alive";
+     
+        if (body != null) request.body = body;
+
+        http.StreamedResponse streamedResponse = await client.send(request);
+        final int statusCode = streamedResponse.statusCode;
+      final Map<String, String> responseHeaders = streamedResponse.headers;
+    
+        onConnect?.call(statusCode, responseHeaders);
+      
+        print("inside streamed response");
+        final stream = streamedResponse.stream
+      .transform(utf8.decoder)
+      .transform(const LineSplitter());
+        try{ stream.listen(
+    (event) {
+      onData?.call(event);
+      if (event.isNotEmpty) {
+        print('🔹 SSE Event Received: $event');
+        print(event.toString());
+      //   final parsedEvent = SSEEventModel.fromRawSSE(event);
+      //   ref.read(sseFramesProvider.notifier).addFrame(requestId, parsedEvent);
+       
+      }
+    },
+    onError: (error) {
+      (error, stackTrace) => onError?.call(error, stackTrace);
+      print('🔹 SSE Error: $error');
+      // ref.read(sseFramesProvider.notifier).update((state) {
+      //   return {...state, requestId: [...(state[requestId] ?? []), 'Error: $error']};
+      // });
+      // finalizeRequestModel(requestId);
+    },
+    onDone: () {
+      onDone?.call();
+       print('🔹 SSE Stream Done');
+   //   finalizeRequestModel(requestId);
+    },
+ );}catch (e, stackTrace) {
+      print('🔹 Error connecting to SSE: $e');
+      onError?.call(e, stackTrace);
+      //_reconnect(onData, onError, onDone);
+    }
+      //   print("streamedResponse"+streamedResponse.headers.toString());
+      //  // var buffer = await convertStreamedResponse(streamedResponse);
+      //  // print(buffer.body.toString());
+      //   if(streamedResponse.headers['content-type']?.contains('text/event-stream') == true){
+      //     print("has the content type");
+      //   }
+      //   stopwatch.stop();
+      //   Stream<String>? utf8Stream;
+      //   if (streamedResponse.statusCode == 200) {
+         
+      //     utf8Stream = await streamedResponse.stream
+      //         .transform(utf8.decoder)
+      //         .transform(const LineSplitter());
+      //     print("utf8stream"+utf8Stream.toString());
+
+      //     await for (final event in utf8Stream) {
+      //       print("inside eventloop");
+      //       if (event.isNotEmpty) {
+      //         print('🔹 SSE Event Received: $event');
+      //       }
+      //     }
+      //   }
+      //   print("just before return ing null");
+      }
+    }
+    
+}
\ No newline at end of file
diff --git a/packages/apidash_core/lib/services/services.dart b/packages/apidash_core/lib/services/services.dart
index d155e9c70..a5bb7fbd0 100644
--- a/packages/apidash_core/lib/services/services.dart
+++ b/packages/apidash_core/lib/services/services.dart
@@ -1,2 +1,3 @@
 export 'http_client_manager.dart';
 export 'http_service.dart';
+export 'http_sse_service.dart';
\ No newline at end of file

From 7aa25c71a38bb9a746666dc3a47877fcabfa66d2 Mon Sep 17 00:00:00 2001
From: Clasherzz <govindkm20044@gmail.com>
Date: Tue, 1 Apr 2025 01:08:27 +0530
Subject: [PATCH 2/8] corrected sse service

---
 lib/providers/collection_providers.dart       | 233 +++++++++---------
 .../request_pane/request_pane.dart            |   2 +-
 .../details_card/response_pane.dart           |  27 +-
 .../home_page/editor_pane/url_card.dart       |   6 +-
 lib/utils/ui_utils.dart                       |   1 +
 lib/widgets/texts.dart                        |   1 +
 packages/apidash_core/lib/consts.dart         |   4 +-
 .../lib/models/http_response_model.dart       |   2 +
 .../models/http_response_model.freezed.dart   |  44 +++-
 .../lib/models/http_response_model.g.dart     |   5 +
 .../lib/services/http_client_manager.dart     |  15 +-
 .../lib/services/http_service.dart            | 173 ++-----------
 .../lib/services/http_sse_service.dart        | 213 +++++++++-------
 .../lib/utils/http_request_utils.dart         |   2 +-
 packages/apidash_core/pubspec.yaml            |   1 +
 .../lib/tokens/colors.dart                    |   2 +
 pubspec.lock                                  |   8 +
 17 files changed, 349 insertions(+), 390 deletions(-)

diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart
index c6b061854..c65cd814e 100644
--- a/lib/providers/collection_providers.dart
+++ b/lib/providers/collection_providers.dart
@@ -22,10 +22,10 @@ final selectedRequestModelProvider = StateProvider<RequestModel?>((ref) {
   }
 });
 
-class SSEFramesNotifier extends StateNotifier<Map<String, List<dynamic>>> {
+class SSEFramesNotifier extends StateNotifier<Map<String, List<SSEEventModel>>> {
   SSEFramesNotifier() : super({});
 
-  void addFrame(String requestId, dynamic frame) {
+  void addFrame(String requestId, String frame) {
     state = {
       ...state,
       requestId: [...(state[requestId] ?? []), SSEEventModel.fromRawSSE(frame)],
@@ -50,7 +50,7 @@ class SSEFramesNotifier extends StateNotifier<Map<String, List<dynamic>>> {
 
 // Provide it globally
 final sseFramesProvider =
-    StateNotifierProvider<SSEFramesNotifier, Map<String, List<dynamic>>>(
+    StateNotifierProvider<SSEFramesNotifier, Map<String, List<SSEEventModel>>>(
   (ref) => SSEFramesNotifier(),
 );
 
@@ -297,6 +297,7 @@ class CollectionStateNotifier
     unsave();
   }
 
+  
   Future<void> sendRequest() async {
     final requestId = ref.read(selectedIdStateProvider);
     ref.read(codePaneVisibleStateProvider.notifier).state = false;
@@ -324,140 +325,132 @@ class CollectionStateNotifier
     state = map;
 
     bool noSSL = ref.read(settingsProvider).isSSLDisabled;
-    
-    state = map;
-    var responseRec = await sendSSERequest(
-      requestId,
-      apiType,
-      substitutedHttpRequestModel,
-      defaultUriScheme: defaultUriScheme,
-      noSSL: noSSL,
-      onConnect: (statusCode, headers) {
+    if(apiType == APIType.sse){
+      print("inside sendrequest apitype,sse");
+      List<SSEEventModel> frames; 
+      await sendSSERequest(
+        requestId,
+        apiType,
+        substitutedHttpRequestModel,
+        defaultUriScheme: defaultUriScheme,
+        noSSL: noSSL,
+        onConnect: (statusCode, responseHeaders, requestHeaders,duration) {
+          print("inside sse onconnect");
+        ref.read(sseFramesProvider.notifier).clearFrames(requestId);
         map = {...state!};
+        print(statusCode);
+      print(responseHeaders);
+      print(requestHeaders);
         map[requestId] = requestModel.copyWith(
         responseStatus: statusCode,
         message: kResponseCodeReasons[statusCode],
-        httpResponseModel: null,
+        httpResponseModel: baseHttpResponseModel.copyWith(
+          statusCode: statusCode,
+          headers: responseHeaders,
+          requestHeaders: requestHeaders,
+          time: duration,
+        ),
         isWorking: true,
       );
+      state = map;
       
        
       },
       onData: (response) {
           ref.read(sseFramesProvider.notifier).addFrame(requestId, response);
       },
+      onError: (error, stackTrace) {
+        frames = ref.read(sseFramesProvider)[requestId] ?? [];
+        map = {...state!};
+        map[requestId] = requestModel.copyWith(
+          responseStatus: 500,
+          message: error.toString(),
+          httpResponseModel: baseHttpResponseModel.copyWith(
+            sseEvents: frames,
+          ),
+          isWorking: false,
+        );
+        state = map;
+      },
+      onDone: () {
+        frames = ref.read(sseFramesProvider)[requestId] ?? [];
+        map = {...state!};
+        map[requestId] = requestModel.copyWith(
+          httpResponseModel: baseHttpResponseModel.copyWith(
+            sseEvents: frames,
+          ),
+          isWorking: false,
+        );
+        state = map;
+      },
+      onCancel: () {
+        frames = ref.read(sseFramesProvider)[requestId] ?? [];
+        map = {...state!};
+        map[requestId] = requestModel.copyWith(
+          responseStatus: -1,
+          message: kMsgRequestCancelled,
+          isWorking: false,
+        );
+        state = map;
+      },
+      );
+      return;
+    }
+    var responseRec = await sendHttpRequest(
+      requestId,
+      apiType,
+      substitutedHttpRequestModel,
+      defaultUriScheme: defaultUriScheme,
+      noSSL: noSSL,
     );
 
     late final RequestModel newRequestModel;
-  //   if (responseRec.$1 == null && responseRec.$4 == null) {
-  //     print("inside first if");
-      
-  //     newRequestModel = requestModel.copyWith(
-  //       responseStatus: -1,
-  //       message: responseRec.$3,
-  //       isWorking: false,
-  //     );
-  //   } else if(responseRec.$1 != null){
-  //      print("inside second if");
-  //     final httpResponseModel = baseHttpResponseModel.fromResponse(
-  //       response: responseRec.$1!,
-  //       time: responseRec.$2!,
-  //     );
-  // //     if(responseRec.$1!.headers['content-type']?.contains('text/event-stream') ?? false){
-        
-  // //       Stream.value(responseRec.$1!.bodyBytes  as List<int>).byteStream.transform(utf8.decoder).transform(const LineSplitter());
-
-  // //   await for (final event in utf8Stream) {
-  // //     if (event.isNotEmpty) {
-  // //       yield SSEEventModel.fromRawSSE(event);  // ✅ Emit each event lazily
-  // //     }
-  // //   }
-  // // }
-  //     // }
-  //     int statusCode = responseRec.$1!.statusCode;
-  //     newRequestModel = requestModel.copyWith(
-  //       responseStatus: statusCode,
-  //       message: kResponseCodeReasons[statusCode],
-  //       httpResponseModel: httpResponseModel,
-  //       isWorking: false,
-  //     );
-  //     String newHistoryId = getNewUuid();
-  //     HistoryRequestModel model = HistoryRequestModel(
-  //       historyId: newHistoryId,
-  //       metaData: HistoryMetaModel(
-  //         historyId: newHistoryId,
-  //         requestId: requestId,
-  //         apiType: requestModel.apiType,
-  //         name: requestModel.name,
-  //         url: substitutedHttpRequestModel.url,
-  //         method: substitutedHttpRequestModel.method,
-  //         responseStatus: statusCode,
-  //         timeStamp: DateTime.now(),
-  //       ),
-  //       httpRequestModel: substitutedHttpRequestModel,
-  //       httpResponseModel: httpResponseModel,
-  //     );
-  //     ref.read(historyMetaStateNotifier.notifier).addHistoryRequest(model);
-  //   }else if(responseRec.$4 != null){
-  //     print("inside else if");
-      
-  //     // final httpResponseModel = baseHttpResponseModel.fromResponse(
-  //     //   response: responseRec.$4!,
-  //     //   time: responseRec.$2!,
-  //     // );
-  // //     if(responseRec.$1!.headers['content-type']?.contains('text/event-stream') ?? false){
-        
-  // //       Stream.value(responseRec.$1!.bodyBytes  as List<int>).byteStream.transform(utf8.decoder).transform(const LineSplitter());
-
-  // //   await for (final event in utf8Stream) {
-  // //     if (event.isNotEmpty) {
-  // //       yield SSEEventModel.fromRawSSE(event);  // ✅ Emit each event lazily
-  // //     }
-  // //   }
-  // // }
-  //     // }
-  // //    var streamedResponse = responseRec.$4!;
-  // //    final stream = streamedResponse.stream
-  // //     .transform(utf8.decoder)
-  // //     .transform(const LineSplitter());
-
-  // // stream.listen(
-  // //   (event) {
-  // //     if (event.isNotEmpty) {
-  // //       print('🔹 SSE Event Received: $event');
-  // //       print(event.toString());
-  // //       // final parsedEvent = SSEEventModel.fromRawSSE(event);
-  // //       // ref.read(sseFramesProvider.notifier).addFrame(requestId, parsedEvent);
-       
-  // //     }
-  // //   },
-  // //   onError: (error) {
-  // //     // ref.read(sseFramesProvider.notifier).update((state) {
-  // //     //   return {...state, requestId: [...(state[requestId] ?? []), 'Error: $error']};
-  // //     // });
-  // //     // finalizeRequestModel(requestId);
-  // //   },
-  // //   onDone: () {
-  // //  //   finalizeRequestModel(requestId);
-  // //   },
-  // // );
-
-  // // // newRequestModel = requestModel.copyWith(
-  // // //       responseStatus: 200,
-  // // //       message: kResponseCodeReasons[200],
-  // //       httpResponseModel: httpResponseModel,
-  // //       isWorking: false,
-  // //     );
-  //   }
-
-  //   // update state with response data
-  //   // map = {...state!};
-  //   // map[requestId] = newRequestModel;
-  //   // state = map;
-
-  //   unsave();
+    if (responseRec.$1 == null) {
+      newRequestModel = requestModel.copyWith(
+        responseStatus: -1,
+        message: responseRec.$3,
+        isWorking: false,
+      );
+    } else {
+      final httpResponseModel = baseHttpResponseModel.fromResponse(
+        response: responseRec.$1!,
+        time: responseRec.$2!,
+      );
+      int statusCode = responseRec.$1!.statusCode;
+      newRequestModel = requestModel.copyWith(
+        responseStatus: statusCode,
+        message: kResponseCodeReasons[statusCode],
+        httpResponseModel: httpResponseModel,
+        isWorking: false,
+      );
+      String newHistoryId = getNewUuid();
+      HistoryRequestModel model = HistoryRequestModel(
+        historyId: newHistoryId,
+        metaData: HistoryMetaModel(
+          historyId: newHistoryId,
+          requestId: requestId,
+          apiType: requestModel.apiType,
+          name: requestModel.name,
+          url: substitutedHttpRequestModel.url,
+          method: substitutedHttpRequestModel.method,
+          responseStatus: statusCode,
+          timeStamp: DateTime.now(),
+        ),
+        httpRequestModel: substitutedHttpRequestModel,
+        httpResponseModel: httpResponseModel,
+      );
+      ref.read(historyMetaStateNotifier.notifier).addHistoryRequest(model);
+    }
+
+    // update state with response data
+    map = {...state!};
+    map[requestId] = newRequestModel;
+    state = map;
+
+    unsave();
   }
 
+
   void cancelRequest() {
     final id = ref.read(selectedIdStateProvider);
     cancelHttpRequest(id);
diff --git a/lib/screens/home_page/editor_pane/details_card/request_pane/request_pane.dart b/lib/screens/home_page/editor_pane/details_card/request_pane/request_pane.dart
index 9c852c71b..c15deab83 100644
--- a/lib/screens/home_page/editor_pane/details_card/request_pane/request_pane.dart
+++ b/lib/screens/home_page/editor_pane/details_card/request_pane/request_pane.dart
@@ -15,7 +15,7 @@ class EditRequestPane extends ConsumerWidget {
     final apiType = ref
         .watch(selectedRequestModelProvider.select((value) => value?.apiType));
     return switch (apiType) {
-      APIType.rest => const EditRestRequestPane(),
+      APIType.rest || APIType.sse => const EditRestRequestPane(),
       APIType.graphql => const EditGraphQLRequestPane(),
       _ => kSizedBoxEmpty,
     };
diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
index ab4350f60..14440d92d 100644
--- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart
+++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
@@ -26,6 +26,7 @@ class ResponsePane extends ConsumerWidget{
 
     
     if (isWorking && sseFramesNotifier.isEmpty) {
+      print("inside sending widget"+sseFramesNotifier.isEmpty.toString());
       return SendingWidget(
         startSendingTime: startSendingTime,
       );
@@ -91,14 +92,13 @@ class ResponseTabs extends ConsumerWidget {
     return ResponseTabView(
       selectedId: selectedId,
       children: [
-        if (apiType == APIType.rest || apiType == APIType.graphql) ...[
-          SSEView(requestId: selectedId ),  
-        const ResponseHeadersTab(),
+        if (apiType == APIType.rest || apiType == APIType.graphql) ...const[
+           ResponseBodyTab(),
+           ResponseHeadersTab(),
+        ]else ...[
+          SSEView(requestId: selectedId),
+          const ResponseHeadersTab(),
         ]
-        // ] else if (apiType == APIType.rest) ...const [
-        //   WebsocketResponseView(),
-        //   ResponseHeadersTab(),
-        // ],
       
       ],
     );
@@ -128,20 +128,11 @@ class ResponseHeadersTab extends ConsumerWidget {
     final responseHttpHeaders = ref.watch(selectedRequestModelProvider
             .select((value) => value?.httpResponseModel?.headers)) ??
         {};
-    // final requestWebSocketHeaders = ref.watch(selectedRequestModelProvider
-    //         .select((value) => value?.webSocketResponseModel?.requestHeaders)) ??
-    //     {};
-    // final responseWebSocketHeaders = ref.watch(selectedRequestModelProvider
-    //         .select((value) => value?.webSocketResponseModel?.headers)) ??
-    //     {};
+   
     final apiType = ref
         .watch(selectedRequestModelProvider.select((value) => value?.apiType));
     switch (apiType!) {
-      // case APIType.rest || APIType.graphql:
-      //   return ResponseHeaders(
-      //     responseHeaders: responseHttpHeaders,
-      //     requestHeaders: requestHttpHeaders,
-      //   );
+     
       case APIType.rest:
         return ResponseHeaders(
           responseHeaders: responseHttpHeaders,
diff --git a/lib/screens/home_page/editor_pane/url_card.dart b/lib/screens/home_page/editor_pane/url_card.dart
index 829bc5c97..a5828d0f7 100644
--- a/lib/screens/home_page/editor_pane/url_card.dart
+++ b/lib/screens/home_page/editor_pane/url_card.dart
@@ -33,12 +33,12 @@ class EditorPaneRequestURLCard extends ConsumerWidget {
             ? Row(
                 children: [
                   switch (apiType) {
-                    APIType.rest => const DropdownButtonHTTPMethod(),
+                    APIType.rest || APIType.sse => const DropdownButtonHTTPMethod(),
                     APIType.graphql => kSizedBoxEmpty,
                     null => kSizedBoxEmpty,
                   },
                   switch (apiType) {
-                    APIType.rest => kHSpacer5,
+                    APIType.rest || APIType.sse => kHSpacer5,
                     _ => kHSpacer8,
                   },
                   const Expanded(
@@ -49,7 +49,7 @@ class EditorPaneRequestURLCard extends ConsumerWidget {
             : Row(
                 children: [
                   switch (apiType) {
-                    APIType.rest => const DropdownButtonHTTPMethod(),
+                    APIType.rest  || APIType.sse=> const DropdownButtonHTTPMethod(),
                     APIType.graphql => kSizedBoxEmpty,
                     null => kSizedBoxEmpty,
                   },
diff --git a/lib/utils/ui_utils.dart b/lib/utils/ui_utils.dart
index 4f72a1a3f..50458f72a 100644
--- a/lib/utils/ui_utils.dart
+++ b/lib/utils/ui_utils.dart
@@ -36,6 +36,7 @@ Color getAPIColor(
         method,
       ),
     APIType.graphql => kColorGQL,
+    APIType.sse => kColorSSE,
   };
   if (brightness == Brightness.dark) {
     col = getDarkModeColor(col);
diff --git a/lib/widgets/texts.dart b/lib/widgets/texts.dart
index c64a71b27..834936c56 100644
--- a/lib/widgets/texts.dart
+++ b/lib/widgets/texts.dart
@@ -20,6 +20,7 @@ class SidebarRequestCardTextBox extends StatelessWidget {
         switch (apiType) {
           APIType.rest => method.abbr,
           APIType.graphql => apiType.abbr,
+          APIType.sse => apiType.abbr,
         },
         textAlign: TextAlign.center,
         style: TextStyle(
diff --git a/packages/apidash_core/lib/consts.dart b/packages/apidash_core/lib/consts.dart
index 26a24879d..6bb48bcbf 100644
--- a/packages/apidash_core/lib/consts.dart
+++ b/packages/apidash_core/lib/consts.dart
@@ -2,8 +2,8 @@ import 'dart:convert';
 
 enum APIType {
   rest("HTTP", "HTTP"),
-  graphql("GraphQL", "GQL");
-//  sse("SSE", "SSE");
+  graphql("GraphQL", "GQL"),
+  sse("SSE", "SSE");
 
   const APIType(this.label, this.abbr);
   final String label;
diff --git a/packages/apidash_core/lib/models/http_response_model.dart b/packages/apidash_core/lib/models/http_response_model.dart
index 914aaa577..5e49a4f9e 100644
--- a/packages/apidash_core/lib/models/http_response_model.dart
+++ b/packages/apidash_core/lib/models/http_response_model.dart
@@ -1,6 +1,7 @@
 import 'dart:io';
 import 'dart:convert';
 import 'dart:typed_data';
+import 'package:apidash_core/apidash_core.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'package:collection/collection.dart' show mergeMaps;
 import 'package:http/http.dart';
@@ -56,6 +57,7 @@ class HttpResponseModel with _$HttpResponseModel {
     String? formattedBody,
     @Uint8ListConverter() Uint8List? bodyBytes,
     @DurationConverter() Duration? time,
+    List<SSEEventModel>? sseEvents,
   }) = _HttpResponseModel;
 
   factory HttpResponseModel.fromJson(Map<String, Object?> json) =>
diff --git a/packages/apidash_core/lib/models/http_response_model.freezed.dart b/packages/apidash_core/lib/models/http_response_model.freezed.dart
index 45071986a..68fe1923b 100644
--- a/packages/apidash_core/lib/models/http_response_model.freezed.dart
+++ b/packages/apidash_core/lib/models/http_response_model.freezed.dart
@@ -29,6 +29,7 @@ mixin _$HttpResponseModel {
   Uint8List? get bodyBytes => throw _privateConstructorUsedError;
   @DurationConverter()
   Duration? get time => throw _privateConstructorUsedError;
+  List<SSEEventModel>? get sseEvents => throw _privateConstructorUsedError;
 
   /// Serializes this HttpResponseModel to a JSON map.
   Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
@@ -53,7 +54,8 @@ abstract class $HttpResponseModelCopyWith<$Res> {
       String? body,
       String? formattedBody,
       @Uint8ListConverter() Uint8List? bodyBytes,
-      @DurationConverter() Duration? time});
+      @DurationConverter() Duration? time,
+      List<SSEEventModel>? sseEvents});
 }
 
 /// @nodoc
@@ -78,6 +80,7 @@ class _$HttpResponseModelCopyWithImpl<$Res, $Val extends HttpResponseModel>
     Object? formattedBody = freezed,
     Object? bodyBytes = freezed,
     Object? time = freezed,
+    Object? sseEvents = freezed,
   }) {
     return _then(_value.copyWith(
       statusCode: freezed == statusCode
@@ -108,6 +111,10 @@ class _$HttpResponseModelCopyWithImpl<$Res, $Val extends HttpResponseModel>
           ? _value.time
           : time // ignore: cast_nullable_to_non_nullable
               as Duration?,
+      sseEvents: freezed == sseEvents
+          ? _value.sseEvents
+          : sseEvents // ignore: cast_nullable_to_non_nullable
+              as List<SSEEventModel>?,
     ) as $Val);
   }
 }
@@ -127,7 +134,8 @@ abstract class _$$HttpResponseModelImplCopyWith<$Res>
       String? body,
       String? formattedBody,
       @Uint8ListConverter() Uint8List? bodyBytes,
-      @DurationConverter() Duration? time});
+      @DurationConverter() Duration? time,
+      List<SSEEventModel>? sseEvents});
 }
 
 /// @nodoc
@@ -150,6 +158,7 @@ class __$$HttpResponseModelImplCopyWithImpl<$Res>
     Object? formattedBody = freezed,
     Object? bodyBytes = freezed,
     Object? time = freezed,
+    Object? sseEvents = freezed,
   }) {
     return _then(_$HttpResponseModelImpl(
       statusCode: freezed == statusCode
@@ -180,6 +189,10 @@ class __$$HttpResponseModelImplCopyWithImpl<$Res>
           ? _value.time
           : time // ignore: cast_nullable_to_non_nullable
               as Duration?,
+      sseEvents: freezed == sseEvents
+          ? _value._sseEvents
+          : sseEvents // ignore: cast_nullable_to_non_nullable
+              as List<SSEEventModel>?,
     ));
   }
 }
@@ -195,9 +208,11 @@ class _$HttpResponseModelImpl extends _HttpResponseModel {
       this.body,
       this.formattedBody,
       @Uint8ListConverter() this.bodyBytes,
-      @DurationConverter() this.time})
+      @DurationConverter() this.time,
+      final List<SSEEventModel>? sseEvents})
       : _headers = headers,
         _requestHeaders = requestHeaders,
+        _sseEvents = sseEvents,
         super._();
 
   factory _$HttpResponseModelImpl.fromJson(Map<String, dynamic> json) =>
@@ -235,10 +250,19 @@ class _$HttpResponseModelImpl extends _HttpResponseModel {
   @override
   @DurationConverter()
   final Duration? time;
+  final List<SSEEventModel>? _sseEvents;
+  @override
+  List<SSEEventModel>? get sseEvents {
+    final value = _sseEvents;
+    if (value == null) return null;
+    if (_sseEvents is EqualUnmodifiableListView) return _sseEvents;
+    // ignore: implicit_dynamic_type
+    return EqualUnmodifiableListView(value);
+  }
 
   @override
   String toString() {
-    return 'HttpResponseModel(statusCode: $statusCode, headers: $headers, requestHeaders: $requestHeaders, body: $body, formattedBody: $formattedBody, bodyBytes: $bodyBytes, time: $time)';
+    return 'HttpResponseModel(statusCode: $statusCode, headers: $headers, requestHeaders: $requestHeaders, body: $body, formattedBody: $formattedBody, bodyBytes: $bodyBytes, time: $time, sseEvents: $sseEvents)';
   }
 
   @override
@@ -255,7 +279,9 @@ class _$HttpResponseModelImpl extends _HttpResponseModel {
             (identical(other.formattedBody, formattedBody) ||
                 other.formattedBody == formattedBody) &&
             const DeepCollectionEquality().equals(other.bodyBytes, bodyBytes) &&
-            (identical(other.time, time) || other.time == time));
+            (identical(other.time, time) || other.time == time) &&
+            const DeepCollectionEquality()
+                .equals(other._sseEvents, _sseEvents));
   }
 
   @JsonKey(includeFromJson: false, includeToJson: false)
@@ -268,7 +294,8 @@ class _$HttpResponseModelImpl extends _HttpResponseModel {
       body,
       formattedBody,
       const DeepCollectionEquality().hash(bodyBytes),
-      time);
+      time,
+      const DeepCollectionEquality().hash(_sseEvents));
 
   /// Create a copy of HttpResponseModel
   /// with the given fields replaced by the non-null parameter values.
@@ -295,7 +322,8 @@ abstract class _HttpResponseModel extends HttpResponseModel {
       final String? body,
       final String? formattedBody,
       @Uint8ListConverter() final Uint8List? bodyBytes,
-      @DurationConverter() final Duration? time}) = _$HttpResponseModelImpl;
+      @DurationConverter() final Duration? time,
+      final List<SSEEventModel>? sseEvents}) = _$HttpResponseModelImpl;
   const _HttpResponseModel._() : super._();
 
   factory _HttpResponseModel.fromJson(Map<String, dynamic> json) =
@@ -317,6 +345,8 @@ abstract class _HttpResponseModel extends HttpResponseModel {
   @override
   @DurationConverter()
   Duration? get time;
+  @override
+  List<SSEEventModel>? get sseEvents;
 
   /// Create a copy of HttpResponseModel
   /// with the given fields replaced by the non-null parameter values.
diff --git a/packages/apidash_core/lib/models/http_response_model.g.dart b/packages/apidash_core/lib/models/http_response_model.g.dart
index 186fd152f..f3e174018 100644
--- a/packages/apidash_core/lib/models/http_response_model.g.dart
+++ b/packages/apidash_core/lib/models/http_response_model.g.dart
@@ -20,6 +20,10 @@ _$HttpResponseModelImpl _$$HttpResponseModelImplFromJson(Map json) =>
       bodyBytes:
           const Uint8ListConverter().fromJson(json['bodyBytes'] as List<int>?),
       time: const DurationConverter().fromJson((json['time'] as num?)?.toInt()),
+      sseEvents: (json['sseEvents'] as List<dynamic>?)
+          ?.map((e) =>
+              SSEEventModel.fromJson(Map<String, Object?>.from(e as Map)))
+          .toList(),
     );
 
 Map<String, dynamic> _$$HttpResponseModelImplToJson(
@@ -32,4 +36,5 @@ Map<String, dynamic> _$$HttpResponseModelImplToJson(
       'formattedBody': instance.formattedBody,
       'bodyBytes': const Uint8ListConverter().toJson(instance.bodyBytes),
       'time': const DurationConverter().toJson(instance.time),
+      'sseEvents': instance.sseEvents?.map((e) => e.toJson()).toList(),
     };
diff --git a/packages/apidash_core/lib/services/http_client_manager.dart b/packages/apidash_core/lib/services/http_client_manager.dart
index bec23214f..2dc13d821 100644
--- a/packages/apidash_core/lib/services/http_client_manager.dart
+++ b/packages/apidash_core/lib/services/http_client_manager.dart
@@ -1,5 +1,4 @@
 import 'dart:io';
-import 'dart:collection';
 import 'package:flutter/foundation.dart';
 import 'package:http/http.dart' as http;
 import 'package:http/io_client.dart';
@@ -15,7 +14,7 @@ class HttpClientManager {
   static final HttpClientManager _instance = HttpClientManager._internal();
   static const int _maxCancelledRequests = 100;
   final Map<String, http.Client> _clients = {};
-  final Queue<String> _cancelledRequests = Queue();
+  final Set<String> _cancelledRequests = {};
 
   factory HttpClientManager() {
     return _instance;
@@ -38,9 +37,9 @@ class HttpClientManager {
       _clients[requestId]?.close();
       _clients.remove(requestId);
 
-      _cancelledRequests.addLast(requestId);
-      while (_cancelledRequests.length > _maxCancelledRequests) {
-        _cancelledRequests.removeFirst();
+      _cancelledRequests.add(requestId);
+      if (_cancelledRequests.length > _maxCancelledRequests) {
+        _cancelledRequests.remove(_cancelledRequests.first);
       }
     }
   }
@@ -49,6 +48,10 @@ class HttpClientManager {
     return _cancelledRequests.contains(requestId);
   }
 
+  void removeCancelledRequest(String requestId) {
+    _cancelledRequests.remove(requestId);
+  }
+
   void closeClient(String requestId) {
     if (_clients.containsKey(requestId)) {
       _clients[requestId]?.close();
@@ -59,4 +62,4 @@ class HttpClientManager {
   bool hasActiveClient(String requestId) {
     return _clients.containsKey(requestId);
   }
-}
+}
\ No newline at end of file
diff --git a/packages/apidash_core/lib/services/http_service.dart b/packages/apidash_core/lib/services/http_service.dart
index 4457ebafb..6f5488aad 100644
--- a/packages/apidash_core/lib/services/http_service.dart
+++ b/packages/apidash_core/lib/services/http_service.dart
@@ -9,20 +9,19 @@ import '../utils/utils.dart';
 import 'http_client_manager.dart';
 
 typedef HttpResponse = http.Response;
-typedef StreamedResponse = http.StreamedResponse;
 
 final httpClientManager = HttpClientManager();
 
-Future<(HttpResponse?, Duration?, String?,StreamedResponse?)> sendHttpRequest(
+Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
   String requestId,
   APIType apiType,
   HttpRequestModel requestModel, {
   SupportedUriSchemes defaultUriScheme = kDefaultUriScheme,
   bool noSSL = false,
-  Function(String event)? onData,
-  Function(Object error, StackTrace stackTrace)? onError,
-  Function()? onDone,
 }) async {
+  if (httpClientManager.wasRequestCancelled(requestId)) {
+    httpClientManager.removeCancelledRequest(requestId);
+  }
   final client = httpClientManager.createClient(requestId, noSSL: noSSL);
 
   (Uri?, String?) uriRec = getValidRequestUri(
@@ -39,78 +38,6 @@ Future<(HttpResponse?, Duration?, String?,StreamedResponse?)> sendHttpRequest(
     try {
       Stopwatch stopwatch = Stopwatch()..start();
       if (apiType == APIType.rest) {
-        print("inside sse http serviec");
-        // ✅ SSE Handling (POST, PUT, etc. with Body)
-        var request = http.Request(requestModel.method.name.toUpperCase(), requestUrl);
-        
-        request.headers.addAll(headers);
-        request.headers["Accept"] = "text/event-stream";
-      request.headers["Cache-Control"] = "no-cache";
-      request.headers["Connection"] = "keep-alive";
-     
-        if (body != null) request.body = body;
-
-        http.StreamedResponse streamedResponse = await client.send(request);
-        print("inside streamed response");
-        final stream = streamedResponse.stream
-      .transform(utf8.decoder)
-      .transform(const LineSplitter());
-        try{ stream.listen(
-    (event) {
-      onData?.call(event);
-      if (event.isNotEmpty) {
-        print('🔹 SSE Event Received: $event');
-        print(event.toString());
-      //   final parsedEvent = SSEEventModel.fromRawSSE(event);
-      //   ref.read(sseFramesProvider.notifier).addFrame(requestId, parsedEvent);
-       
-      }
-    },
-    onError: (error) {
-      (error, stackTrace) => onError?.call(error, stackTrace);
-      print('🔹 SSE Error: $error');
-      // ref.read(sseFramesProvider.notifier).update((state) {
-      //   return {...state, requestId: [...(state[requestId] ?? []), 'Error: $error']};
-      // });
-      // finalizeRequestModel(requestId);
-    },
-    onDone: () {
-      onDone?.call();
-       print('🔹 SSE Stream Done');
-   //   finalizeRequestModel(requestId);
-    },
- );}catch (e, stackTrace) {
-      print('🔹 Error connecting to SSE: $e');
-      onError?.call(e, stackTrace);
-      //_reconnect(onData, onError, onDone);
-    }
-      //   print("streamedResponse"+streamedResponse.headers.toString());
-      //  // var buffer = await convertStreamedResponse(streamedResponse);
-      //  // print(buffer.body.toString());
-      //   if(streamedResponse.headers['content-type']?.contains('text/event-stream') == true){
-      //     print("has the content type");
-      //   }
-      //   stopwatch.stop();
-      //   Stream<String>? utf8Stream;
-      //   if (streamedResponse.statusCode == 200) {
-         
-      //     utf8Stream = await streamedResponse.stream
-      //         .transform(utf8.decoder)
-      //         .transform(const LineSplitter());
-      //     print("utf8stream"+utf8Stream.toString());
-
-      //     await for (final event in utf8Stream) {
-      //       print("inside eventloop");
-      //       if (event.isNotEmpty) {
-      //         print('🔹 SSE Event Received: $event');
-      //       }
-      //     }
-      //   }
-      //   print("just before return ing null");
-        return (null, stopwatch.elapsed, null,streamedResponse);
-      }
-      if (apiType == APIType.rest) {
-        print("iside second rest");
         var isMultiPartRequest =
             requestModel.bodyContentType == ContentType.formdata;
 
@@ -147,37 +74,27 @@ Future<(HttpResponse?, Duration?, String?,StreamedResponse?)> sendHttpRequest(
               }
             }
             http.StreamedResponse multiPartResponse =
-                await multiPartRequest.send();
+                await client.send(multiPartRequest);
+
             stopwatch.stop();
             http.Response convertedMultiPartResponse =
                 await convertStreamedResponse(multiPartResponse);
-            return (convertedMultiPartResponse, stopwatch.elapsed, null,null);
+            return (convertedMultiPartResponse, stopwatch.elapsed, null);
           }
         }
-        switch (requestModel.method) {
-          case HTTPVerb.get:
-            response = await client.get(requestUrl, headers: headers);
-            break;
-          case HTTPVerb.head:
-            response = await client.head(requestUrl, headers: headers);
-            break;
-          case HTTPVerb.post:
-            response =
-                await client.post(requestUrl, headers: headers, body: body);
-            break;
-          case HTTPVerb.put:
-            response =
-                await client.put(requestUrl, headers: headers, body: body);
-            break;
-          case HTTPVerb.patch:
-            response =
-                await client.patch(requestUrl, headers: headers, body: body);
-            break;
-          case HTTPVerb.delete:
-            response =
-                await client.delete(requestUrl, headers: headers, body: body);
-            break;
-        }
+        response = switch (requestModel.method) {
+          HTTPVerb.get => await client.get(requestUrl, headers: headers),
+          HTTPVerb.head => response =
+              await client.head(requestUrl, headers: headers),
+          HTTPVerb.post => response =
+              await client.post(requestUrl, headers: headers, body: body),
+          HTTPVerb.put => response =
+              await client.put(requestUrl, headers: headers, body: body),
+          HTTPVerb.patch => response =
+              await client.patch(requestUrl, headers: headers, body: body),
+          HTTPVerb.delete => response =
+              await client.delete(requestUrl, headers: headers, body: body),
+        };
       }
       if (apiType == APIType.graphql) {
         var requestBody = getGraphQLBody(requestModel);
@@ -198,59 +115,21 @@ Future<(HttpResponse?, Duration?, String?,StreamedResponse?)> sendHttpRequest(
         );
       }
       stopwatch.stop();
-      return (response, stopwatch.elapsed, null,null);
+      return (response, stopwatch.elapsed, null);
     } catch (e) {
-      print("inside catch");
       if (httpClientManager.wasRequestCancelled(requestId)) {
-        return (null, null, kMsgRequestCancelled,null);
+        return (null, null, kMsgRequestCancelled);
       }
-      return (null, null, e.toString(),null);
+      return (null, null, e.toString());
     } finally {
-      print("inside finallyy");
       httpClientManager.closeClient(requestId);
     }
   } else {
-    return (null, null, uriRec.$2,null);
+    return (null, null, uriRec.$2);
   }
 }
 
 void cancelHttpRequest(String? requestId) {
+  print("cancelHttpRequest: $requestId");
   httpClientManager.cancelRequest(requestId);
-}
-
-
-// void startSSE() async {
-//   var url = Uri.parse('https://sse.dev/test');
-//   var client = HttpClient();
-
-//   try {
-//     var request = await client.getUrl(url);
-    
-
-//     var response = await request.close();
-
-//     // Ensure it's a successful SSE connection
-//     if (response.statusCode == 200) {
-//       print("✅ Connected to SSE stream");
-
-//       response.transform(utf8.decoder).listen(
-//         (data) {
-//           print("🔹 SSE Event Received: $data");
-//         },
-//         onError: (error) {
-//           print("❌ SSE Error: $error");
-//         },
-//         onDone: () {
-//           print("🔌 SSE Stream Closed");
-//         },
-//         cancelOnError: true,
-//       );
-//     } else {
-//       print("❌ Failed to connect: ${response.statusCode}");
-//     }
-//   } catch (e) {
-//     print("❌ Exception: $e");
-//   }
-// }
-
-
+}
\ No newline at end of file
diff --git a/packages/apidash_core/lib/services/http_sse_service.dart b/packages/apidash_core/lib/services/http_sse_service.dart
index 3a0b9777d..2055d9bb2 100644
--- a/packages/apidash_core/lib/services/http_sse_service.dart
+++ b/packages/apidash_core/lib/services/http_sse_service.dart
@@ -1,11 +1,37 @@
 import 'dart:async';
 import 'dart:convert';
+import 'dart:io';
 import 'package:http/http.dart' as http;
+import 'package:http_interceptor/http_interceptor.dart';
+import 'package:seed/consts.dart';
 import '../consts.dart';
 import '../models/models.dart';
 import '../utils/utils.dart';
 import 'http_service.dart';
 
+class LoggingInterceptor implements InterceptorContract {
+  Map<String, String>? interceptedHeaders;
+
+  @override
+  FutureOr<BaseRequest> interceptRequest({required BaseRequest request}) async {
+    interceptedHeaders = request.headers;
+    print("Headers: \${request.headers}");
+    return request;
+  }
+
+  @override
+  Future<BaseResponse> interceptResponse({required BaseResponse response}) async {
+    print("Response: \${response.statusCode}");
+    print("Headers: \${response.headers}");
+    return response;
+  }
+
+  @override
+  FutureOr<bool> shouldInterceptRequest() => true;
+
+  @override
+  FutureOr<bool> shouldInterceptResponse() => true;
+}
 
 Future<void> sendSSERequest(
   String requestId,
@@ -13,101 +39,118 @@ Future<void> sendSSERequest(
   HttpRequestModel requestModel, {
   SupportedUriSchemes defaultUriScheme = kDefaultUriScheme,
   bool noSSL = false,
-  Function(int statusCode, Map<String, String> headers)? onConnect,
+  Function(int statusCode, Map<String, String> headers, Map<String, String>? interceptedHeaders, Duration?)? onConnect,
   Function(String event)? onData,
   Function(Object error, StackTrace stackTrace)? onError,
   Function()? onDone,
+  Function()? onCancel,
 }) async {
-  final client = httpClientManager.createClient(requestId, noSSL: noSSL);
+  if (httpClientManager.wasRequestCancelled(requestId)) {
+    httpClientManager.removeCancelledRequest(requestId);
+  }
+  final interceptor = LoggingInterceptor();
+  final baseClient = httpClientManager.createClient(requestId, noSSL: noSSL);
+  final client = InterceptedClient.build(interceptors: [interceptor], client: baseClient);
 
-  (Uri?, String?) uriRec = getValidRequestUri(
-    requestModel.url,
-    requestModel.enabledParams,
-    defaultUriScheme: defaultUriScheme,
-  );
+  try {
+    (Uri?, String?) uriRec = getValidRequestUri(
+      requestModel.url,
+      requestModel.enabledParams,
+      defaultUriScheme: defaultUriScheme,
+    );
+    if (uriRec.$1 == null) return;
 
-  if (uriRec.$1 != null) {
     Uri requestUrl = uriRec.$1!;
-    Map<String, String> headers = requestModel.enabledHeadersMap;
-    HttpResponse? response;
-    String? body;
-   
-      Stopwatch stopwatch = Stopwatch()..start();
-      if (apiType == APIType.rest) {
-        print("inside sse http serviec");
-        // ✅ SSE Handling (POST, PUT, etc. with Body)
-        var request = http.Request(requestModel.method.name.toUpperCase(), requestUrl);
+    var isMultiPartRequest = requestModel.bodyContentType == ContentType.formdata;
+    var stopwatch = Stopwatch()..start();
+    late http.StreamedResponse streamedResponse;
+    if (apiType == APIType.sse) {
+      print("Inside SSE HTTP service");
+      
+      if (isMultiPartRequest) {
+        var multiPartRequest = http.MultipartRequest(
+          requestModel.method.name.toUpperCase(),
+          requestUrl,
+        );
+        multiPartRequest.headers.addAll(requestModel.enabledHeadersMap);
+
+        for (var formData in requestModel.formDataList) {
+          if (formData.type == FormDataType.text) {
+            multiPartRequest.fields[formData.name] = formData.value;
+          } else {
+            multiPartRequest.files.add(await http.MultipartFile.fromPath(formData.name, formData.value));
+          }
+        }
+
+        streamedResponse = await multiPartRequest.send();
+        stopwatch.stop();
+        
         
-        request.headers.addAll(headers);
-        request.headers["Accept"] = "text/event-stream";
-      request.headers["Cache-Control"] = "no-cache";
-      request.headers["Connection"] = "keep-alive";
-     
-        if (body != null) request.body = body;
+       
+      } else {
+        var request = http.Request(requestModel.method.name.toUpperCase(), requestUrl);
+        request.headers.addAll(requestModel.enabledHeadersMap);
 
-        http.StreamedResponse streamedResponse = await client.send(request);
-        final int statusCode = streamedResponse.statusCode;
-      final Map<String, String> responseHeaders = streamedResponse.headers;
-    
-        onConnect?.call(statusCode, responseHeaders);
-      
-        print("inside streamed response");
-        final stream = streamedResponse.stream
-      .transform(utf8.decoder)
-      .transform(const LineSplitter());
-        try{ stream.listen(
-    (event) {
-      onData?.call(event);
-      if (event.isNotEmpty) {
-        print('🔹 SSE Event Received: $event');
-        print(event.toString());
-      //   final parsedEvent = SSEEventModel.fromRawSSE(event);
-      //   ref.read(sseFramesProvider.notifier).addFrame(requestId, parsedEvent);
+        if (kMethodsWithBody.contains(requestModel.method) && requestModel.body != null) {
+          request.body = requestModel.body!;
+          request.headers[HttpHeaders.contentTypeHeader] = requestModel.bodyContentType.header;
+        }
+
+        streamedResponse = await client.send(request);
+        stopwatch.stop();
+        
+        
        
       }
-    },
-    onError: (error) {
-      (error, stackTrace) => onError?.call(error, stackTrace);
-      print('🔹 SSE Error: $error');
-      // ref.read(sseFramesProvider.notifier).update((state) {
-      //   return {...state, requestId: [...(state[requestId] ?? []), 'Error: $error']};
-      // });
-      // finalizeRequestModel(requestId);
-    },
-    onDone: () {
-      onDone?.call();
-       print('🔹 SSE Stream Done');
-   //   finalizeRequestModel(requestId);
-    },
- );}catch (e, stackTrace) {
-      print('🔹 Error connecting to SSE: $e');
-      onError?.call(e, stackTrace);
-      //_reconnect(onData, onError, onDone);
+      print("before connect");
+      print("status code: ${streamedResponse.statusCode}");
+      print("headers: ${streamedResponse.headers}");
+      onConnect?.call(
+          streamedResponse.statusCode, streamedResponse.headers, interceptor.interceptedHeaders, stopwatch.elapsed
+      );
+      print("after connect");
+      final stream = streamedResponse.stream
+          .transform(utf8.decoder)
+          .transform(const LineSplitter());
+      stream.listen(
+        (event) {
+          onData?.call(event);
+          if (event.isNotEmpty) {
+            print('🔹 SSE Event Received: $event');
+            print(event.toString());
+            
+          }
+        },
+        onError: (error) {
+            if (httpClientManager.wasRequestCancelled(requestId)) {
+              print("inside cancelled");
+              onCancel?.call(); 
+              return;   
+             }
+          (error, stackTrace) => onError?.call(error, stackTrace);
+          print('🔹 SSE Error: $error');
+        },
+        onDone: () {
+          if (httpClientManager.wasRequestCancelled(requestId)) {
+            print("inside cancelled");
+              onCancel?.call();  
+              return;  
+          }
+          onDone?.call();
+          print('🔹 SSE Stream Done');
+        }
+      );
     }
-      //   print("streamedResponse"+streamedResponse.headers.toString());
-      //  // var buffer = await convertStreamedResponse(streamedResponse);
-      //  // print(buffer.body.toString());
-      //   if(streamedResponse.headers['content-type']?.contains('text/event-stream') == true){
-      //     print("has the content type");
-      //   }
-      //   stopwatch.stop();
-      //   Stream<String>? utf8Stream;
-      //   if (streamedResponse.statusCode == 200) {
-         
-      //     utf8Stream = await streamedResponse.stream
-      //         .transform(utf8.decoder)
-      //         .transform(const LineSplitter());
-      //     print("utf8stream"+utf8Stream.toString());
+  } catch (e, stackTrace) {
+    print("inside catch");
+    onError?.call(e, stackTrace);
+  }
+  // finally{
+  //   print("finally");
+  //   if (httpClientManager.wasRequestCancelled(requestId)) {
+  //     onCancel?.call();    
+  //   }
+  //   httpClientManager.closeClient(requestId);
+  // }
+}
 
-      //     await for (final event in utf8Stream) {
-      //       print("inside eventloop");
-      //       if (event.isNotEmpty) {
-      //         print('🔹 SSE Event Received: $event');
-      //       }
-      //     }
-      //   }
-      //   print("just before return ing null");
-      }
-    }
-    
-}
\ No newline at end of file
diff --git a/packages/apidash_core/lib/utils/http_request_utils.dart b/packages/apidash_core/lib/utils/http_request_utils.dart
index b5eab42cc..24bc36753 100644
--- a/packages/apidash_core/lib/utils/http_request_utils.dart
+++ b/packages/apidash_core/lib/utils/http_request_utils.dart
@@ -93,7 +93,7 @@ List<NameValueModel>? getEnabledRows(
 
 String? getRequestBody(APIType type, HttpRequestModel httpRequestModel) {
   return switch (type) {
-    APIType.rest =>
+    APIType.rest || APIType.sse =>
       (httpRequestModel.hasJsonData || httpRequestModel.hasTextData)
           ? httpRequestModel.body
           : null,
diff --git a/packages/apidash_core/pubspec.yaml b/packages/apidash_core/pubspec.yaml
index 13aaea079..344a20aac 100644
--- a/packages/apidash_core/pubspec.yaml
+++ b/packages/apidash_core/pubspec.yaml
@@ -23,6 +23,7 @@ dependencies:
     path: ../postman
   seed: ^0.0.3
   xml: ^6.3.0
+  http_interceptor: ^2.0.0
 
 dev_dependencies:
   flutter_test:
diff --git a/packages/apidash_design_system/lib/tokens/colors.dart b/packages/apidash_design_system/lib/tokens/colors.dart
index 11943bd32..92b8c061f 100644
--- a/packages/apidash_design_system/lib/tokens/colors.dart
+++ b/packages/apidash_design_system/lib/tokens/colors.dart
@@ -26,6 +26,8 @@ final kColorHttpMethodDelete = Colors.red.shade800;
 
 final kColorGQL = Colors.pink.shade600;
 
+final kColorSSE = Colors.purple.shade600;
+
 const kHintOpacity = 0.6;
 const kForegroundOpacity = 0.05;
 const kOverlayBackgroundOpacity = 0.5;
diff --git a/pubspec.lock b/pubspec.lock
index b16f69dd4..c4a0694fe 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -783,6 +783,14 @@ packages:
       url: "https://pub.dev"
     source: hosted
     version: "1.3.0"
+  http_interceptor:
+    dependency: transitive
+    description:
+      name: http_interceptor
+      sha256: "288c6ded4a2c66de2730a16b30cbd29d05d042a5e61304d9b4be0e16378f4082"
+      url: "https://pub.dev"
+    source: hosted
+    version: "2.0.0"
   http_multi_server:
     dependency: transitive
     description:

From 6123091f0026e07f13dca7a26a0b2e4774c009d0 Mon Sep 17 00:00:00 2001
From: Clasherzz <govindkm20044@gmail.com>
Date: Tue, 1 Apr 2025 01:19:31 +0530
Subject: [PATCH 3/8] removed debug prints

---
 .../lib/services/http_sse_service.dart        | 34 +++++++------------
 1 file changed, 12 insertions(+), 22 deletions(-)

diff --git a/packages/apidash_core/lib/services/http_sse_service.dart b/packages/apidash_core/lib/services/http_sse_service.dart
index 2055d9bb2..c411a0b8c 100644
--- a/packages/apidash_core/lib/services/http_sse_service.dart
+++ b/packages/apidash_core/lib/services/http_sse_service.dart
@@ -15,14 +15,12 @@ class LoggingInterceptor implements InterceptorContract {
   @override
   FutureOr<BaseRequest> interceptRequest({required BaseRequest request}) async {
     interceptedHeaders = request.headers;
-    print("Headers: \${request.headers}");
     return request;
   }
 
   @override
   Future<BaseResponse> interceptResponse({required BaseResponse response}) async {
-    print("Response: \${response.statusCode}");
-    print("Headers: \${response.headers}");
+
     return response;
   }
 
@@ -102,28 +100,20 @@ Future<void> sendSSERequest(
         
        
       }
-      print("before connect");
-      print("status code: ${streamedResponse.statusCode}");
-      print("headers: ${streamedResponse.headers}");
       onConnect?.call(
           streamedResponse.statusCode, streamedResponse.headers, interceptor.interceptedHeaders, stopwatch.elapsed
       );
-      print("after connect");
+      
       final stream = streamedResponse.stream
           .transform(utf8.decoder)
           .transform(const LineSplitter());
       stream.listen(
         (event) {
           onData?.call(event);
-          if (event.isNotEmpty) {
-            print('🔹 SSE Event Received: $event');
-            print(event.toString());
-            
-          }
         },
         onError: (error) {
             if (httpClientManager.wasRequestCancelled(requestId)) {
-              print("inside cancelled");
+             
               onCancel?.call(); 
               return;   
              }
@@ -137,20 +127,20 @@ Future<void> sendSSERequest(
               return;  
           }
           onDone?.call();
-          print('🔹 SSE Stream Done');
+        
         }
       );
     }
   } catch (e, stackTrace) {
-    print("inside catch");
+    
     onError?.call(e, stackTrace);
   }
-  // finally{
-  //   print("finally");
-  //   if (httpClientManager.wasRequestCancelled(requestId)) {
-  //     onCancel?.call();    
-  //   }
-  //   httpClientManager.closeClient(requestId);
-  // }
+  finally{
+ 
+    if (httpClientManager.wasRequestCancelled(requestId)) {
+      onCancel?.call();    
+    }
+  
+  }
 }
 

From 7e633f5ab15aa4ac70510565b74cc0ff837fd0d8 Mon Sep 17 00:00:00 2001
From: Clasherzz <govindkm20044@gmail.com>
Date: Tue, 1 Apr 2025 11:01:24 +0530
Subject: [PATCH 4/8] working on cancellation

---
 .../home_page/editor_pane/details_card/response_pane.dart  | 7 +++----
 packages/apidash_core/lib/services/http_service.dart       | 1 -
 2 files changed, 3 insertions(+), 5 deletions(-)

diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
index 14440d92d..3def68ca4 100644
--- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart
+++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
@@ -193,7 +193,6 @@ class _SSEViewState extends ConsumerState<SSEView> {
     final displayFrames = _isAtBottom ? frames : _pausedFrames;
 
     return Scaffold(
-      appBar: AppBar(title: Text("SSE Stream - ${widget.requestId}")),
       body: Column(
         children: [
           Expanded(
@@ -213,8 +212,8 @@ class _SSEViewState extends ConsumerState<SSEView> {
                       child: Column(
                         crossAxisAlignment: CrossAxisAlignment.start,
                         children: [
-                          if (event.event.isEmpty) _buildTag("Event", "message", Colors.blue),
-                          _buildData(event.data),
+                          if (event.event.isNotEmpty) _buildTag("Event", "message", Colors.blue),
+                          if (event.data.isNotEmpty) _buildData(event.data),
                           if (event.id != null && event.id!.isNotEmpty) _buildTag("ID", event.id!, Colors.orange),
                           if (event.retry != null) _buildTag("Retry", "${event.retry} ms", Colors.purple),
                           if (event.customFields != null && event.customFields!.isNotEmpty)
@@ -282,7 +281,7 @@ class _SSEViewState extends ConsumerState<SSEView> {
         try {
           final jsonData = json.decode(data);
           final formattedJson = const JsonEncoder.withIndent('  ').convert(jsonData);
-          final bool shouldCollapse = formattedJson.length > 2;
+          final bool shouldCollapse = formattedJson.length > 100;
 
           return Column(
             crossAxisAlignment: CrossAxisAlignment.start,
diff --git a/packages/apidash_core/lib/services/http_service.dart b/packages/apidash_core/lib/services/http_service.dart
index 6f5488aad..436fb2a8c 100644
--- a/packages/apidash_core/lib/services/http_service.dart
+++ b/packages/apidash_core/lib/services/http_service.dart
@@ -130,6 +130,5 @@ Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
 }
 
 void cancelHttpRequest(String? requestId) {
-  print("cancelHttpRequest: $requestId");
   httpClientManager.cancelRequest(requestId);
 }
\ No newline at end of file

From 64601b1daad28cac78f61e4b1721087f77f6bdef Mon Sep 17 00:00:00 2001
From: Clasherzz <govindkm20044@gmail.com>
Date: Tue, 1 Apr 2025 20:29:15 +0530
Subject: [PATCH 5/8] removed print statements

---
 .../lib/models/http_sse_event_model.dart      | 18 ++++---
 .../models/http_sse_event_model.freezed.dart  | 49 ++++++++++++-------
 .../lib/models/http_sse_event_model.g.dart    |  2 +
 .../lib/services/http_sse_service.dart        |  1 -
 4 files changed, 43 insertions(+), 27 deletions(-)

diff --git a/packages/apidash_core/lib/models/http_sse_event_model.dart b/packages/apidash_core/lib/models/http_sse_event_model.dart
index 64aa58a3e..f633d3baa 100644
--- a/packages/apidash_core/lib/models/http_sse_event_model.dart
+++ b/packages/apidash_core/lib/models/http_sse_event_model.dart
@@ -13,11 +13,12 @@ class SSEEventModel with _$SSEEventModel {
     anyMap: true,
   )
   const factory SSEEventModel({
-    @Default("") String event, // Custom event name
-    @Default("") String data, // Event data (main payload)
-    String? id, // Last event ID for reconnection
-    int? retry, // Reconnect interval in milliseconds
-    Map<String, String>? customFields, // Additional metadata
+    @Default("") String event, 
+    @Default("") String data,
+    @Default("") String comment,
+    String? id, 
+    int? retry, 
+    Map<String, String>? customFields, 
   }) = _SSEEventModel;
 
   factory SSEEventModel.fromJson(Map<String, Object?> json) =>
@@ -26,12 +27,12 @@ class SSEEventModel with _$SSEEventModel {
   /// Parses raw SSE data into an SSEEventModel
   static SSEEventModel fromRawSSE(String rawEvent) {
     final Map<String, String> fields = {};
-    String? event, data, id;
+    String? event, data, id ,comment;
     int? retry;
 
     for (var line in LineSplitter.split(rawEvent)) {
       if (line.startsWith(":")) {
-        continue; // Ignore comments
+        comment = line;// Ignore comments
       }
       final parts = line.split(": ");
       if (parts.length < 2) continue;
@@ -44,7 +45,7 @@ class SSEEventModel with _$SSEEventModel {
           event = value;
           break;
         case "data":
-          data = (data ?? "") + value + "\n"; // Multi-line data support
+          data = (data ?? "") + value; 
           break;
         case "id":
           id = value;
@@ -60,6 +61,7 @@ class SSEEventModel with _$SSEEventModel {
     return SSEEventModel(
       event: event ?? "",
       data: data?.trim() ?? "",
+      comment: comment ?? "",
       id: id,
       retry: retry,
       customFields: fields.isNotEmpty ? fields : null,
diff --git a/packages/apidash_core/lib/models/http_sse_event_model.freezed.dart b/packages/apidash_core/lib/models/http_sse_event_model.freezed.dart
index d35f2c256..2e16d7079 100644
--- a/packages/apidash_core/lib/models/http_sse_event_model.freezed.dart
+++ b/packages/apidash_core/lib/models/http_sse_event_model.freezed.dart
@@ -20,13 +20,11 @@ SSEEventModel _$SSEEventModelFromJson(Map<String, dynamic> json) {
 
 /// @nodoc
 mixin _$SSEEventModel {
-  String get event => throw _privateConstructorUsedError; // Custom event name
-  String get data =>
-      throw _privateConstructorUsedError; // Event data (main payload)
-  String? get id =>
-      throw _privateConstructorUsedError; // Last event ID for reconnection
-  int? get retry =>
-      throw _privateConstructorUsedError; // Reconnect interval in milliseconds
+  String get event => throw _privateConstructorUsedError;
+  String get data => throw _privateConstructorUsedError;
+  String get comment => throw _privateConstructorUsedError;
+  String? get id => throw _privateConstructorUsedError;
+  int? get retry => throw _privateConstructorUsedError;
   Map<String, String>? get customFields => throw _privateConstructorUsedError;
 
   /// Serializes this SSEEventModel to a JSON map.
@@ -48,6 +46,7 @@ abstract class $SSEEventModelCopyWith<$Res> {
   $Res call(
       {String event,
       String data,
+      String comment,
       String? id,
       int? retry,
       Map<String, String>? customFields});
@@ -70,6 +69,7 @@ class _$SSEEventModelCopyWithImpl<$Res, $Val extends SSEEventModel>
   $Res call({
     Object? event = null,
     Object? data = null,
+    Object? comment = null,
     Object? id = freezed,
     Object? retry = freezed,
     Object? customFields = freezed,
@@ -83,6 +83,10 @@ class _$SSEEventModelCopyWithImpl<$Res, $Val extends SSEEventModel>
           ? _value.data
           : data // ignore: cast_nullable_to_non_nullable
               as String,
+      comment: null == comment
+          ? _value.comment
+          : comment // ignore: cast_nullable_to_non_nullable
+              as String,
       id: freezed == id
           ? _value.id
           : id // ignore: cast_nullable_to_non_nullable
@@ -110,6 +114,7 @@ abstract class _$$SSEEventModelImplCopyWith<$Res>
   $Res call(
       {String event,
       String data,
+      String comment,
       String? id,
       int? retry,
       Map<String, String>? customFields});
@@ -130,6 +135,7 @@ class __$$SSEEventModelImplCopyWithImpl<$Res>
   $Res call({
     Object? event = null,
     Object? data = null,
+    Object? comment = null,
     Object? id = freezed,
     Object? retry = freezed,
     Object? customFields = freezed,
@@ -143,6 +149,10 @@ class __$$SSEEventModelImplCopyWithImpl<$Res>
           ? _value.data
           : data // ignore: cast_nullable_to_non_nullable
               as String,
+      comment: null == comment
+          ? _value.comment
+          : comment // ignore: cast_nullable_to_non_nullable
+              as String,
       id: freezed == id
           ? _value.id
           : id // ignore: cast_nullable_to_non_nullable
@@ -166,6 +176,7 @@ class _$SSEEventModelImpl extends _SSEEventModel {
   const _$SSEEventModelImpl(
       {this.event = "",
       this.data = "",
+      this.comment = "",
       this.id,
       this.retry,
       final Map<String, String>? customFields})
@@ -178,19 +189,17 @@ class _$SSEEventModelImpl extends _SSEEventModel {
   @override
   @JsonKey()
   final String event;
-// Custom event name
   @override
   @JsonKey()
   final String data;
-// Event data (main payload)
+  @override
+  @JsonKey()
+  final String comment;
   @override
   final String? id;
-// Last event ID for reconnection
   @override
   final int? retry;
-// Reconnect interval in milliseconds
   final Map<String, String>? _customFields;
-// Reconnect interval in milliseconds
   @override
   Map<String, String>? get customFields {
     final value = _customFields;
@@ -202,7 +211,7 @@ class _$SSEEventModelImpl extends _SSEEventModel {
 
   @override
   String toString() {
-    return 'SSEEventModel(event: $event, data: $data, id: $id, retry: $retry, customFields: $customFields)';
+    return 'SSEEventModel(event: $event, data: $data, comment: $comment, id: $id, retry: $retry, customFields: $customFields)';
   }
 
   @override
@@ -212,6 +221,7 @@ class _$SSEEventModelImpl extends _SSEEventModel {
             other is _$SSEEventModelImpl &&
             (identical(other.event, event) || other.event == event) &&
             (identical(other.data, data) || other.data == data) &&
+            (identical(other.comment, comment) || other.comment == comment) &&
             (identical(other.id, id) || other.id == id) &&
             (identical(other.retry, retry) || other.retry == retry) &&
             const DeepCollectionEquality()
@@ -220,7 +230,7 @@ class _$SSEEventModelImpl extends _SSEEventModel {
 
   @JsonKey(includeFromJson: false, includeToJson: false)
   @override
-  int get hashCode => Object.hash(runtimeType, event, data, id, retry,
+  int get hashCode => Object.hash(runtimeType, event, data, comment, id, retry,
       const DeepCollectionEquality().hash(_customFields));
 
   /// Create a copy of SSEEventModel
@@ -243,6 +253,7 @@ abstract class _SSEEventModel extends SSEEventModel {
   const factory _SSEEventModel(
       {final String event,
       final String data,
+      final String comment,
       final String? id,
       final int? retry,
       final Map<String, String>? customFields}) = _$SSEEventModelImpl;
@@ -252,13 +263,15 @@ abstract class _SSEEventModel extends SSEEventModel {
       _$SSEEventModelImpl.fromJson;
 
   @override
-  String get event; // Custom event name
+  String get event;
+  @override
+  String get data;
   @override
-  String get data; // Event data (main payload)
+  String get comment;
   @override
-  String? get id; // Last event ID for reconnection
+  String? get id;
   @override
-  int? get retry; // Reconnect interval in milliseconds
+  int? get retry;
   @override
   Map<String, String>? get customFields;
 
diff --git a/packages/apidash_core/lib/models/http_sse_event_model.g.dart b/packages/apidash_core/lib/models/http_sse_event_model.g.dart
index b85ec871d..17c1ccdf6 100644
--- a/packages/apidash_core/lib/models/http_sse_event_model.g.dart
+++ b/packages/apidash_core/lib/models/http_sse_event_model.g.dart
@@ -10,6 +10,7 @@ _$SSEEventModelImpl _$$SSEEventModelImplFromJson(Map json) =>
     _$SSEEventModelImpl(
       event: json['event'] as String? ?? "",
       data: json['data'] as String? ?? "",
+      comment: json['comment'] as String? ?? "",
       id: json['id'] as String?,
       retry: (json['retry'] as num?)?.toInt(),
       customFields: (json['customFields'] as Map?)?.map(
@@ -21,6 +22,7 @@ Map<String, dynamic> _$$SSEEventModelImplToJson(_$SSEEventModelImpl instance) =>
     <String, dynamic>{
       'event': instance.event,
       'data': instance.data,
+      'comment': instance.comment,
       'id': instance.id,
       'retry': instance.retry,
       'customFields': instance.customFields,
diff --git a/packages/apidash_core/lib/services/http_sse_service.dart b/packages/apidash_core/lib/services/http_sse_service.dart
index c411a0b8c..1fe885d8f 100644
--- a/packages/apidash_core/lib/services/http_sse_service.dart
+++ b/packages/apidash_core/lib/services/http_sse_service.dart
@@ -63,7 +63,6 @@ Future<void> sendSSERequest(
     var stopwatch = Stopwatch()..start();
     late http.StreamedResponse streamedResponse;
     if (apiType == APIType.sse) {
-      print("Inside SSE HTTP service");
       
       if (isMultiPartRequest) {
         var multiPartRequest = http.MultipartRequest(

From 8f68aaf30f5e1516ef817dd5723e1bc3b50c9e7f Mon Sep 17 00:00:00 2001
From: Clasherzz <govindkm20044@gmail.com>
Date: Tue, 1 Apr 2025 21:59:08 +0530
Subject: [PATCH 6/8] working on response

---
 lib/providers/collection_providers.dart       |  6 ++---
 .../details_card/response_pane.dart           | 24 ++++++++++++++-----
 2 files changed, 20 insertions(+), 10 deletions(-)

diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart
index c65cd814e..b308ca548 100644
--- a/lib/providers/collection_providers.dart
+++ b/lib/providers/collection_providers.dart
@@ -335,12 +335,10 @@ class CollectionStateNotifier
         defaultUriScheme: defaultUriScheme,
         noSSL: noSSL,
         onConnect: (statusCode, responseHeaders, requestHeaders,duration) {
-          print("inside sse onconnect");
+        
         ref.read(sseFramesProvider.notifier).clearFrames(requestId);
         map = {...state!};
-        print(statusCode);
-      print(responseHeaders);
-      print(requestHeaders);
+       
         map[requestId] = requestModel.copyWith(
         responseStatus: statusCode,
         message: kResponseCodeReasons[statusCode],
diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
index 3def68ca4..f37cab1f8 100644
--- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart
+++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
@@ -23,20 +23,29 @@ class ResponsePane extends ConsumerWidget{
     final message = ref
         .watch(selectedRequestModelProvider.select((value) => value?.message));
     final sseFramesNotifier =  ref.watch(sseFramesProvider.select((state) => state[selectedId] ?? []));
-
+    final apiType = ref.watch(selectedRequestModelProvider.select((value) => value?.apiType));
     
-    if (isWorking && sseFramesNotifier.isEmpty) {
-      print("inside sending widget"+sseFramesNotifier.isEmpty.toString());
+    if (isWorking && apiType == APIType.sse && sseFramesNotifier.isEmpty) {
+     
+      return SendingWidget(
+        startSendingTime: startSendingTime,
+      );
+
+    }
+   
+
+    if (isWorking && apiType != APIType.sse ) {
+     
       return SendingWidget(
         startSendingTime: startSendingTime,
       );
 
     }
 
-    if (responseStatus == null && sseFramesNotifier.isEmpty) {
+    if (responseStatus == null) {
       return const NotSentWidget();
     }
-    if (responseStatus == -1 && sseFramesNotifier.isEmpty) {
+    if (responseStatus == -1) {
       return message == kMsgRequestCancelled
           ? ErrorMessage(
               message: message,
@@ -187,7 +196,10 @@ class _SSEViewState extends ConsumerState<SSEView> {
   Widget build(BuildContext context) {
     final frames = ref.watch(sseFramesProvider.select((state) => state[widget.requestId] ?? []));
 
-    if (_isAtBottom) {
+    // if (_isAtBottom) {
+    //   _pausedFrames = List.from(frames);
+    // }
+    if (_isAtBottom || frames.isEmpty) {
       _pausedFrames = List.from(frames);
     }
     final displayFrames = _isAtBottom ? frames : _pausedFrames;

From 29f93ed42bee826fdfdbe2c181e477ae0d7633cf Mon Sep 17 00:00:00 2001
From: Clasherzz <govindkm20044@gmail.com>
Date: Fri, 4 Apr 2025 00:28:40 +0530
Subject: [PATCH 7/8] corrected sse transform

---
 lib/providers/collection_providers.dart       |  3 +-
 .../lib/services/http_sse_service.dart        | 37 ++++++++++++++++---
 2 files changed, 34 insertions(+), 6 deletions(-)

diff --git a/lib/providers/collection_providers.dart b/lib/providers/collection_providers.dart
index b308ca548..5c7bd8ba1 100644
--- a/lib/providers/collection_providers.dart
+++ b/lib/providers/collection_providers.dart
@@ -26,6 +26,7 @@ class SSEFramesNotifier extends StateNotifier<Map<String, List<SSEEventModel>>>
   SSEFramesNotifier() : super({});
 
   void addFrame(String requestId, String frame) {
+    print(frame+"\n");
     state = {
       ...state,
       requestId: [...(state[requestId] ?? []), SSEEventModel.fromRawSSE(frame)],
@@ -326,7 +327,7 @@ class CollectionStateNotifier
 
     bool noSSL = ref.read(settingsProvider).isSSLDisabled;
     if(apiType == APIType.sse){
-      print("inside sendrequest apitype,sse");
+     
       List<SSEEventModel> frames; 
       await sendSSERequest(
         requestId,
diff --git a/packages/apidash_core/lib/services/http_sse_service.dart b/packages/apidash_core/lib/services/http_sse_service.dart
index 1fe885d8f..dfa1e8ee8 100644
--- a/packages/apidash_core/lib/services/http_sse_service.dart
+++ b/packages/apidash_core/lib/services/http_sse_service.dart
@@ -9,6 +9,29 @@ import '../models/models.dart';
 import '../utils/utils.dart';
 import 'http_service.dart';
 
+
+
+
+
+class SSETransformer extends StreamTransformerBase<String, String> {
+  const SSETransformer();
+
+  @override
+  Stream<String> bind(Stream<String> stream) async* {
+    String buffer = "";
+    await for (final chunk in stream) {
+      buffer += chunk;
+      List<String> frames = buffer.split("\n\n");
+
+    
+      buffer = frames.removeLast();
+
+      for (final frame in frames) {
+        yield frame.trim(); 
+      }
+    }
+  }
+}
 class LoggingInterceptor implements InterceptorContract {
   Map<String, String>? interceptedHeaders;
 
@@ -105,10 +128,14 @@ Future<void> sendSSERequest(
       
       final stream = streamedResponse.stream
           .transform(utf8.decoder)
-          .transform(const LineSplitter());
+          .transform(const SSETransformer());
       stream.listen(
-        (event) {
-          onData?.call(event);
+        (frame) {
+          print("Received frames: $frame");
+          
+              onData?.call(frame);
+          
+         
         },
         onError: (error) {
             if (httpClientManager.wasRequestCancelled(requestId)) {
@@ -117,11 +144,11 @@ Future<void> sendSSERequest(
               return;   
              }
           (error, stackTrace) => onError?.call(error, stackTrace);
-          print('🔹 SSE Error: $error');
+         
         },
         onDone: () {
           if (httpClientManager.wasRequestCancelled(requestId)) {
-            print("inside cancelled");
+           
               onCancel?.call();  
               return;  
           }

From 129a4b671a673f8ff80fbb192d3ef2cece8681f5 Mon Sep 17 00:00:00 2001
From: Clasherzz <govindkm20044@gmail.com>
Date: Fri, 4 Apr 2025 01:06:25 +0530
Subject: [PATCH 8/8] final commit

---
 .../details_card/response_pane.dart            |  2 +-
 .../lib/services/http_client_manager.dart      |  3 +--
 .../lib/services/http_service.dart             |  1 +
 .../lib/services/http_sse_service.dart         | 18 ++++--------------
 4 files changed, 7 insertions(+), 17 deletions(-)

diff --git a/lib/screens/home_page/editor_pane/details_card/response_pane.dart b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
index f37cab1f8..d6563cac0 100644
--- a/lib/screens/home_page/editor_pane/details_card/response_pane.dart
+++ b/lib/screens/home_page/editor_pane/details_card/response_pane.dart
@@ -212,7 +212,7 @@ class _SSEViewState extends ConsumerState<SSEView> {
               controller: _controller,
               itemCount: displayFrames.length,
               itemBuilder: (context, index) {
-                final event = displayFrames[displayFrames.length - index - 1];
+                final event = displayFrames[index];
 
                 return Padding(
                   padding: const EdgeInsets.symmetric(vertical: 4, horizontal: 8),
diff --git a/packages/apidash_core/lib/services/http_client_manager.dart b/packages/apidash_core/lib/services/http_client_manager.dart
index 2dc13d821..e72d7ac9a 100644
--- a/packages/apidash_core/lib/services/http_client_manager.dart
+++ b/packages/apidash_core/lib/services/http_client_manager.dart
@@ -34,10 +34,9 @@ class HttpClientManager {
 
   void cancelRequest(String? requestId) {
     if (requestId != null && _clients.containsKey(requestId)) {
+       _cancelledRequests.add(requestId);
       _clients[requestId]?.close();
       _clients.remove(requestId);
-
-      _cancelledRequests.add(requestId);
       if (_cancelledRequests.length > _maxCancelledRequests) {
         _cancelledRequests.remove(_cancelledRequests.first);
       }
diff --git a/packages/apidash_core/lib/services/http_service.dart b/packages/apidash_core/lib/services/http_service.dart
index 436fb2a8c..0d673758b 100644
--- a/packages/apidash_core/lib/services/http_service.dart
+++ b/packages/apidash_core/lib/services/http_service.dart
@@ -130,5 +130,6 @@ Future<(HttpResponse?, Duration?, String?)> sendHttpRequest(
 }
 
 void cancelHttpRequest(String? requestId) {
+  print("Cancelling request: $requestId");
   httpClientManager.cancelRequest(requestId);
 }
\ No newline at end of file
diff --git a/packages/apidash_core/lib/services/http_sse_service.dart b/packages/apidash_core/lib/services/http_sse_service.dart
index dfa1e8ee8..f7422f411 100644
--- a/packages/apidash_core/lib/services/http_sse_service.dart
+++ b/packages/apidash_core/lib/services/http_sse_service.dart
@@ -131,16 +131,13 @@ Future<void> sendSSERequest(
           .transform(const SSETransformer());
       stream.listen(
         (frame) {
-          print("Received frames: $frame");
-          
-              onData?.call(frame);
-          
-         
+           onData?.call(frame);
         },
         onError: (error) {
+           
             if (httpClientManager.wasRequestCancelled(requestId)) {
-             
-              onCancel?.call(); 
+              onCancel?.call();  
+              
               return;   
              }
           (error, stackTrace) => onError?.call(error, stackTrace);
@@ -148,7 +145,6 @@ Future<void> sendSSERequest(
         },
         onDone: () {
           if (httpClientManager.wasRequestCancelled(requestId)) {
-           
               onCancel?.call();  
               return;  
           }
@@ -161,12 +157,6 @@ Future<void> sendSSERequest(
     
     onError?.call(e, stackTrace);
   }
-  finally{
- 
-    if (httpClientManager.wasRequestCancelled(requestId)) {
-      onCancel?.call();    
-    }
   
-  }
 }