mirror of
https://github.com/foss42/apidash.git
synced 2025-08-06 13:51:20 +08:00
Added SSE ability to HTTPS method (fusion)
This commit is contained in:
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:apidash_core/apidash_core.dart';
|
import 'package:apidash_core/apidash_core.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
@ -311,7 +313,14 @@ class CollectionStateNotifier
|
|||||||
state = map;
|
state = map;
|
||||||
|
|
||||||
bool noSSL = ref.read(settingsProvider).isSSLDisabled;
|
bool noSSL = ref.read(settingsProvider).isSSLDisabled;
|
||||||
var responseRec = await sendHttpRequest(
|
|
||||||
|
(Response?, Duration?, String?) responseRec;
|
||||||
|
HttpResponseModel? respModel;
|
||||||
|
HistoryRequestModel? historyM;
|
||||||
|
RequestModel? newRequestModel;
|
||||||
|
|
||||||
|
responseRec = (null, null, null);
|
||||||
|
final stream = await streamHttpRequest(
|
||||||
requestId,
|
requestId,
|
||||||
apiType,
|
apiType,
|
||||||
substitutedHttpRequestModel,
|
substitutedHttpRequestModel,
|
||||||
@ -319,7 +328,78 @@ class CollectionStateNotifier
|
|||||||
noSSL: noSSL,
|
noSSL: noSSL,
|
||||||
);
|
);
|
||||||
|
|
||||||
late RequestModel newRequestModel;
|
StreamSubscription? sub;
|
||||||
|
final completer = Completer();
|
||||||
|
|
||||||
|
bool isTextStream = false;
|
||||||
|
|
||||||
|
sub = stream.listen((d) async {
|
||||||
|
if (d == null) return;
|
||||||
|
|
||||||
|
isTextStream = ((d.$1 == null && isTextStream) ||
|
||||||
|
(d.$1 == 'text/event-stream' || d.$1 == 'application/x-ndjson'));
|
||||||
|
|
||||||
|
responseRec = (d.$2, d.$3, d.$4);
|
||||||
|
|
||||||
|
if (!isTextStream) {
|
||||||
|
if (completer.isCompleted) return;
|
||||||
|
completer.complete(responseRec);
|
||||||
|
await Future.delayed(Duration(milliseconds: 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (responseRec.$1 != null) {
|
||||||
|
responseRec = (
|
||||||
|
HttpResponse(
|
||||||
|
responseRec.$1!.body,
|
||||||
|
responseRec.$1!.statusCode,
|
||||||
|
request: responseRec.$1!.request,
|
||||||
|
headers: {
|
||||||
|
...(responseRec.$1?.headers ?? {}),
|
||||||
|
'content-type': 'text/event-stream'
|
||||||
|
},
|
||||||
|
isRedirect: responseRec.$1!.isRedirect,
|
||||||
|
reasonPhrase: responseRec.$1!.reasonPhrase,
|
||||||
|
persistentConnection: responseRec.$1!.persistentConnection,
|
||||||
|
),
|
||||||
|
responseRec.$2,
|
||||||
|
responseRec.$3,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
//----------- MAKE CHANGES --------------
|
||||||
|
respModel = respModel?.copyWith(sseOutput: [
|
||||||
|
...(respModel?.sseOutput ?? []),
|
||||||
|
responseRec.$1!.body,
|
||||||
|
]);
|
||||||
|
if (respModel != null) {
|
||||||
|
final nRM = newRequestModel!.copyWith(
|
||||||
|
httpResponseModel: respModel,
|
||||||
|
);
|
||||||
|
map = {...state!};
|
||||||
|
map[requestId] = nRM;
|
||||||
|
state = map;
|
||||||
|
unsave();
|
||||||
|
}
|
||||||
|
//Changing History
|
||||||
|
if (historyM != null && respModel != null) {
|
||||||
|
historyM = historyM!.copyWith(
|
||||||
|
httpResponseModel: respModel!,
|
||||||
|
);
|
||||||
|
ref
|
||||||
|
.read(historyMetaStateNotifier.notifier)
|
||||||
|
.editHistoryRequest(historyM!);
|
||||||
|
}
|
||||||
|
//----------- MAKE CHANGES --------------
|
||||||
|
|
||||||
|
if (completer.isCompleted) return;
|
||||||
|
completer.complete(responseRec);
|
||||||
|
}, onDone: () {
|
||||||
|
sub?.cancel();
|
||||||
|
}, onError: (e) {
|
||||||
|
print('err: $e');
|
||||||
|
});
|
||||||
|
responseRec = await completer.future;
|
||||||
|
|
||||||
if (responseRec.$1 == null) {
|
if (responseRec.$1 == null) {
|
||||||
newRequestModel = requestModel.copyWith(
|
newRequestModel = requestModel.copyWith(
|
||||||
responseStatus: -1,
|
responseStatus: -1,
|
||||||
@ -327,7 +407,7 @@ class CollectionStateNotifier
|
|||||||
isWorking: false,
|
isWorking: false,
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
final httpResponseModel = baseHttpResponseModel.fromResponse(
|
respModel = baseHttpResponseModel.fromResponse(
|
||||||
response: responseRec.$1!,
|
response: responseRec.$1!,
|
||||||
time: responseRec.$2!,
|
time: responseRec.$2!,
|
||||||
);
|
);
|
||||||
@ -335,11 +415,11 @@ class CollectionStateNotifier
|
|||||||
newRequestModel = requestModel.copyWith(
|
newRequestModel = requestModel.copyWith(
|
||||||
responseStatus: statusCode,
|
responseStatus: statusCode,
|
||||||
message: kResponseCodeReasons[statusCode],
|
message: kResponseCodeReasons[statusCode],
|
||||||
httpResponseModel: httpResponseModel,
|
httpResponseModel: respModel,
|
||||||
isWorking: false,
|
isWorking: false,
|
||||||
);
|
);
|
||||||
String newHistoryId = getNewUuid();
|
String newHistoryId = getNewUuid();
|
||||||
HistoryRequestModel model = HistoryRequestModel(
|
historyM = HistoryRequestModel(
|
||||||
historyId: newHistoryId,
|
historyId: newHistoryId,
|
||||||
metaData: HistoryMetaModel(
|
metaData: HistoryMetaModel(
|
||||||
historyId: newHistoryId,
|
historyId: newHistoryId,
|
||||||
@ -352,7 +432,7 @@ class CollectionStateNotifier
|
|||||||
timeStamp: DateTime.now(),
|
timeStamp: DateTime.now(),
|
||||||
),
|
),
|
||||||
httpRequestModel: substitutedHttpRequestModel,
|
httpRequestModel: substitutedHttpRequestModel,
|
||||||
httpResponseModel: httpResponseModel,
|
httpResponseModel: respModel!,
|
||||||
preRequestScript: requestModel.preRequestScript,
|
preRequestScript: requestModel.preRequestScript,
|
||||||
postRequestScript: requestModel.postRequestScript,
|
postRequestScript: requestModel.postRequestScript,
|
||||||
);
|
);
|
||||||
@ -372,7 +452,7 @@ class CollectionStateNotifier
|
|||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
ref.read(historyMetaStateNotifier.notifier).addHistoryRequest(model);
|
ref.read(historyMetaStateNotifier.notifier).addHistoryRequest(historyM!);
|
||||||
}
|
}
|
||||||
|
|
||||||
// update state with response data
|
// update state with response data
|
||||||
|
@ -90,6 +90,21 @@ class HistoryMetaStateNotifier
|
|||||||
await loadHistoryRequest(id);
|
await loadHistoryRequest(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void editHistoryRequest(HistoryRequestModel model) async {
|
||||||
|
final id = model.historyId;
|
||||||
|
state = {
|
||||||
|
...state ?? {},
|
||||||
|
id: model.metaData,
|
||||||
|
};
|
||||||
|
final existingKeys = state?.keys.toList() ?? [];
|
||||||
|
if (!existingKeys.contains(id)) {
|
||||||
|
hiveHandler.setHistoryIds([...existingKeys, id]);
|
||||||
|
}
|
||||||
|
hiveHandler.setHistoryMeta(id, model.metaData.toJson());
|
||||||
|
await hiveHandler.setHistoryRequest(id, model.toJson());
|
||||||
|
await loadHistoryRequest(id);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> clearAllHistory() async {
|
Future<void> clearAllHistory() async {
|
||||||
await hiveHandler.clearAllHistory();
|
await hiveHandler.clearAllHistory();
|
||||||
ref.read(selectedHistoryIdStateProvider.notifier).state = null;
|
ref.read(selectedHistoryIdStateProvider.notifier).state = null;
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:apidash_core/apidash_core.dart';
|
import 'package:apidash_core/apidash_core.dart';
|
||||||
import 'package:apidash/models/models.dart';
|
import 'package:apidash/models/models.dart';
|
||||||
@ -54,6 +56,22 @@ class ResponseBody extends StatelessWidget {
|
|||||||
options.remove(ResponseBodyView.code);
|
options.remove(ResponseBodyView.code);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// print('reM -> ${responseModel.sseOutput}');
|
||||||
|
|
||||||
|
if (responseModel.sseOutput?.isNotEmpty ?? false) {
|
||||||
|
final modifiedBody = responseModel.sseOutput!.join('\n\n');
|
||||||
|
print(modifiedBody);
|
||||||
|
return ResponseBodySuccess(
|
||||||
|
key: Key("${selectedRequestModel!.id}-response"),
|
||||||
|
mediaType: mediaType,
|
||||||
|
options: options,
|
||||||
|
bytes: utf8.encode(modifiedBody),
|
||||||
|
body: modifiedBody,
|
||||||
|
formattedBody: modifiedBody,
|
||||||
|
highlightLanguage: highlightLanguage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return ResponseBodySuccess(
|
return ResponseBodySuccess(
|
||||||
key: Key("${selectedRequestModel!.id}-response"),
|
key: Key("${selectedRequestModel!.id}-response"),
|
||||||
mediaType: mediaType,
|
mediaType: mediaType,
|
||||||
|
@ -53,6 +53,7 @@ class HttpResponseModel with _$HttpResponseModel {
|
|||||||
String? formattedBody,
|
String? formattedBody,
|
||||||
@Uint8ListConverter() Uint8List? bodyBytes,
|
@Uint8ListConverter() Uint8List? bodyBytes,
|
||||||
@DurationConverter() Duration? time,
|
@DurationConverter() Duration? time,
|
||||||
|
List<String>? sseOutput,
|
||||||
}) = _HttpResponseModel;
|
}) = _HttpResponseModel;
|
||||||
|
|
||||||
factory HttpResponseModel.fromJson(Map<String, Object?> json) =>
|
factory HttpResponseModel.fromJson(Map<String, Object?> json) =>
|
||||||
|
@ -30,6 +30,7 @@ mixin _$HttpResponseModel {
|
|||||||
Uint8List? get bodyBytes => throw _privateConstructorUsedError;
|
Uint8List? get bodyBytes => throw _privateConstructorUsedError;
|
||||||
@DurationConverter()
|
@DurationConverter()
|
||||||
Duration? get time => throw _privateConstructorUsedError;
|
Duration? get time => throw _privateConstructorUsedError;
|
||||||
|
List<String>? get sseOutput => throw _privateConstructorUsedError;
|
||||||
|
|
||||||
/// Serializes this HttpResponseModel to a JSON map.
|
/// Serializes this HttpResponseModel to a JSON map.
|
||||||
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
Map<String, dynamic> toJson() => throw _privateConstructorUsedError;
|
||||||
@ -56,6 +57,7 @@ abstract class $HttpResponseModelCopyWith<$Res> {
|
|||||||
String? formattedBody,
|
String? formattedBody,
|
||||||
@Uint8ListConverter() Uint8List? bodyBytes,
|
@Uint8ListConverter() Uint8List? bodyBytes,
|
||||||
@DurationConverter() Duration? time,
|
@DurationConverter() Duration? time,
|
||||||
|
List<String>? sseOutput,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,6 +83,7 @@ class _$HttpResponseModelCopyWithImpl<$Res, $Val extends HttpResponseModel>
|
|||||||
Object? formattedBody = freezed,
|
Object? formattedBody = freezed,
|
||||||
Object? bodyBytes = freezed,
|
Object? bodyBytes = freezed,
|
||||||
Object? time = freezed,
|
Object? time = freezed,
|
||||||
|
Object? sseOutput = freezed,
|
||||||
}) {
|
}) {
|
||||||
return _then(
|
return _then(
|
||||||
_value.copyWith(
|
_value.copyWith(
|
||||||
@ -112,6 +115,10 @@ class _$HttpResponseModelCopyWithImpl<$Res, $Val extends HttpResponseModel>
|
|||||||
? _value.time
|
? _value.time
|
||||||
: time // ignore: cast_nullable_to_non_nullable
|
: time // ignore: cast_nullable_to_non_nullable
|
||||||
as Duration?,
|
as Duration?,
|
||||||
|
sseOutput: freezed == sseOutput
|
||||||
|
? _value.sseOutput
|
||||||
|
: sseOutput // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<String>?,
|
||||||
)
|
)
|
||||||
as $Val,
|
as $Val,
|
||||||
);
|
);
|
||||||
@ -135,6 +142,7 @@ abstract class _$$HttpResponseModelImplCopyWith<$Res>
|
|||||||
String? formattedBody,
|
String? formattedBody,
|
||||||
@Uint8ListConverter() Uint8List? bodyBytes,
|
@Uint8ListConverter() Uint8List? bodyBytes,
|
||||||
@DurationConverter() Duration? time,
|
@DurationConverter() Duration? time,
|
||||||
|
List<String>? sseOutput,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -159,6 +167,7 @@ class __$$HttpResponseModelImplCopyWithImpl<$Res>
|
|||||||
Object? formattedBody = freezed,
|
Object? formattedBody = freezed,
|
||||||
Object? bodyBytes = freezed,
|
Object? bodyBytes = freezed,
|
||||||
Object? time = freezed,
|
Object? time = freezed,
|
||||||
|
Object? sseOutput = freezed,
|
||||||
}) {
|
}) {
|
||||||
return _then(
|
return _then(
|
||||||
_$HttpResponseModelImpl(
|
_$HttpResponseModelImpl(
|
||||||
@ -190,6 +199,10 @@ class __$$HttpResponseModelImplCopyWithImpl<$Res>
|
|||||||
? _value.time
|
? _value.time
|
||||||
: time // ignore: cast_nullable_to_non_nullable
|
: time // ignore: cast_nullable_to_non_nullable
|
||||||
as Duration?,
|
as Duration?,
|
||||||
|
sseOutput: freezed == sseOutput
|
||||||
|
? _value._sseOutput
|
||||||
|
: sseOutput // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<String>?,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -207,8 +220,10 @@ class _$HttpResponseModelImpl extends _HttpResponseModel {
|
|||||||
this.formattedBody,
|
this.formattedBody,
|
||||||
@Uint8ListConverter() this.bodyBytes,
|
@Uint8ListConverter() this.bodyBytes,
|
||||||
@DurationConverter() this.time,
|
@DurationConverter() this.time,
|
||||||
|
final List<String>? sseOutput,
|
||||||
}) : _headers = headers,
|
}) : _headers = headers,
|
||||||
_requestHeaders = requestHeaders,
|
_requestHeaders = requestHeaders,
|
||||||
|
_sseOutput = sseOutput,
|
||||||
super._();
|
super._();
|
||||||
|
|
||||||
factory _$HttpResponseModelImpl.fromJson(Map<String, dynamic> json) =>
|
factory _$HttpResponseModelImpl.fromJson(Map<String, dynamic> json) =>
|
||||||
@ -246,10 +261,19 @@ class _$HttpResponseModelImpl extends _HttpResponseModel {
|
|||||||
@override
|
@override
|
||||||
@DurationConverter()
|
@DurationConverter()
|
||||||
final Duration? time;
|
final Duration? time;
|
||||||
|
final List<String>? _sseOutput;
|
||||||
|
@override
|
||||||
|
List<String>? get sseOutput {
|
||||||
|
final value = _sseOutput;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_sseOutput is EqualUnmodifiableListView) return _sseOutput;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(value);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
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, sseOutput: $sseOutput)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -268,7 +292,11 @@ class _$HttpResponseModelImpl extends _HttpResponseModel {
|
|||||||
(identical(other.formattedBody, formattedBody) ||
|
(identical(other.formattedBody, formattedBody) ||
|
||||||
other.formattedBody == formattedBody) &&
|
other.formattedBody == formattedBody) &&
|
||||||
const DeepCollectionEquality().equals(other.bodyBytes, bodyBytes) &&
|
const DeepCollectionEquality().equals(other.bodyBytes, bodyBytes) &&
|
||||||
(identical(other.time, time) || other.time == time));
|
(identical(other.time, time) || other.time == time) &&
|
||||||
|
const DeepCollectionEquality().equals(
|
||||||
|
other._sseOutput,
|
||||||
|
_sseOutput,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@ -282,6 +310,7 @@ class _$HttpResponseModelImpl extends _HttpResponseModel {
|
|||||||
formattedBody,
|
formattedBody,
|
||||||
const DeepCollectionEquality().hash(bodyBytes),
|
const DeepCollectionEquality().hash(bodyBytes),
|
||||||
time,
|
time,
|
||||||
|
const DeepCollectionEquality().hash(_sseOutput),
|
||||||
);
|
);
|
||||||
|
|
||||||
/// Create a copy of HttpResponseModel
|
/// Create a copy of HttpResponseModel
|
||||||
@ -310,6 +339,7 @@ abstract class _HttpResponseModel extends HttpResponseModel {
|
|||||||
final String? formattedBody,
|
final String? formattedBody,
|
||||||
@Uint8ListConverter() final Uint8List? bodyBytes,
|
@Uint8ListConverter() final Uint8List? bodyBytes,
|
||||||
@DurationConverter() final Duration? time,
|
@DurationConverter() final Duration? time,
|
||||||
|
final List<String>? sseOutput,
|
||||||
}) = _$HttpResponseModelImpl;
|
}) = _$HttpResponseModelImpl;
|
||||||
const _HttpResponseModel._() : super._();
|
const _HttpResponseModel._() : super._();
|
||||||
|
|
||||||
@ -332,6 +362,8 @@ abstract class _HttpResponseModel extends HttpResponseModel {
|
|||||||
@override
|
@override
|
||||||
@DurationConverter()
|
@DurationConverter()
|
||||||
Duration? get time;
|
Duration? get time;
|
||||||
|
@override
|
||||||
|
List<String>? get sseOutput;
|
||||||
|
|
||||||
/// Create a copy of HttpResponseModel
|
/// Create a copy of HttpResponseModel
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@ -21,6 +21,9 @@ _$HttpResponseModelImpl _$$HttpResponseModelImplFromJson(Map json) =>
|
|||||||
json['bodyBytes'] as List<int>?,
|
json['bodyBytes'] as List<int>?,
|
||||||
),
|
),
|
||||||
time: const DurationConverter().fromJson((json['time'] as num?)?.toInt()),
|
time: const DurationConverter().fromJson((json['time'] as num?)?.toInt()),
|
||||||
|
sseOutput: (json['sseOutput'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$$HttpResponseModelImplToJson(
|
Map<String, dynamic> _$$HttpResponseModelImplToJson(
|
||||||
@ -33,4 +36,5 @@ Map<String, dynamic> _$$HttpResponseModelImplToJson(
|
|||||||
'formattedBody': instance.formattedBody,
|
'formattedBody': instance.formattedBody,
|
||||||
'bodyBytes': const Uint8ListConverter().toJson(instance.bodyBytes),
|
'bodyBytes': const Uint8ListConverter().toJson(instance.bodyBytes),
|
||||||
'time': const DurationConverter().toJson(instance.time),
|
'time': const DurationConverter().toJson(instance.time),
|
||||||
|
'sseOutput': instance.sseOutput,
|
||||||
};
|
};
|
||||||
|
@ -165,14 +165,18 @@ http.Request prepareHttpRequest({
|
|||||||
return request;
|
return request;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<Stream<(String?, Duration?, String?)?>> streamHttpRequest(
|
Future<Stream<(String? cT, HttpResponse? resp, Duration? dur, String? err)?>>
|
||||||
|
streamHttpRequest(
|
||||||
String requestId,
|
String requestId,
|
||||||
APIType apiType,
|
APIType apiType,
|
||||||
HttpRequestModel requestModel, {
|
HttpRequestModel requestModel, {
|
||||||
SupportedUriSchemes defaultUriScheme = kDefaultUriScheme,
|
SupportedUriSchemes defaultUriScheme = kDefaultUriScheme,
|
||||||
bool noSSL = false,
|
bool noSSL = false,
|
||||||
}) async {
|
}) async {
|
||||||
final controller = StreamController<(String?, Duration?, String?)?>();
|
final controller =
|
||||||
|
StreamController<
|
||||||
|
(String? cT, HttpResponse? resp, Duration? dur, String? err)?
|
||||||
|
>();
|
||||||
StreamSubscription<String?>? subscription;
|
StreamSubscription<String?>? subscription;
|
||||||
final stopwatch = Stopwatch()..start();
|
final stopwatch = Stopwatch()..start();
|
||||||
|
|
||||||
@ -186,10 +190,10 @@ Future<Stream<(String?, Duration?, String?)?>> streamHttpRequest(
|
|||||||
Future<void> handleError(dynamic error) async {
|
Future<void> handleError(dynamic error) async {
|
||||||
await Future.microtask(() {});
|
await Future.microtask(() {});
|
||||||
if (httpClientManager.wasRequestCancelled(requestId)) {
|
if (httpClientManager.wasRequestCancelled(requestId)) {
|
||||||
controller.add((null, null, kMsgRequestCancelled));
|
controller.add((null, null, null, kMsgRequestCancelled));
|
||||||
httpClientManager.removeCancelledRequest(requestId);
|
httpClientManager.removeCancelledRequest(requestId);
|
||||||
} else {
|
} else {
|
||||||
controller.add((null, null, error.toString()));
|
controller.add((null, null, null, error.toString()));
|
||||||
}
|
}
|
||||||
await cleanup();
|
await cleanup();
|
||||||
}
|
}
|
||||||
@ -200,7 +204,7 @@ Future<Stream<(String?, Duration?, String?)?>> streamHttpRequest(
|
|||||||
};
|
};
|
||||||
|
|
||||||
if (httpClientManager.wasRequestCancelled(requestId)) {
|
if (httpClientManager.wasRequestCancelled(requestId)) {
|
||||||
controller.add((null, null, kMsgRequestCancelled));
|
controller.add((null, null, null, kMsgRequestCancelled));
|
||||||
httpClientManager.removeCancelledRequest(requestId);
|
httpClientManager.removeCancelledRequest(requestId);
|
||||||
controller.close();
|
controller.close();
|
||||||
return controller.stream;
|
return controller.stream;
|
||||||
@ -243,8 +247,25 @@ Future<Stream<(String?, Duration?, String?)?>> streamHttpRequest(
|
|||||||
final streamedResponse = await client.send(multipart);
|
final streamedResponse = await client.send(multipart);
|
||||||
final stream = streamTextResponse(streamedResponse);
|
final stream = streamTextResponse(streamedResponse);
|
||||||
|
|
||||||
|
print(streamedResponse.headers['content-type']);
|
||||||
|
|
||||||
subscription = stream.listen(
|
subscription = stream.listen(
|
||||||
(data) => controller.add((data, stopwatch.elapsed, null)),
|
(data) => controller.add((
|
||||||
|
streamedResponse.headers['content-type'].toString(),
|
||||||
|
data == null
|
||||||
|
? null
|
||||||
|
: HttpResponse.bytes(
|
||||||
|
utf8.encode(data),
|
||||||
|
streamedResponse.statusCode,
|
||||||
|
request: streamedResponse.request,
|
||||||
|
headers: streamedResponse.headers,
|
||||||
|
isRedirect: streamedResponse.isRedirect,
|
||||||
|
persistentConnection: streamedResponse.persistentConnection,
|
||||||
|
reasonPhrase: streamedResponse.reasonPhrase,
|
||||||
|
),
|
||||||
|
stopwatch.elapsed,
|
||||||
|
null,
|
||||||
|
)),
|
||||||
onDone: () => cleanup(),
|
onDone: () => cleanup(),
|
||||||
onError: handleError,
|
onError: handleError,
|
||||||
);
|
);
|
||||||
@ -279,7 +300,22 @@ Future<Stream<(String?, Duration?, String?)?>> streamHttpRequest(
|
|||||||
subscription = stream.listen(
|
subscription = stream.listen(
|
||||||
(data) {
|
(data) {
|
||||||
if (!controller.isClosed) {
|
if (!controller.isClosed) {
|
||||||
controller.add((data, stopwatch.elapsed, null));
|
controller.add((
|
||||||
|
streamedResponse.headers['content-type'].toString(),
|
||||||
|
data == null
|
||||||
|
? null
|
||||||
|
: HttpResponse.bytes(
|
||||||
|
utf8.encode(data),
|
||||||
|
streamedResponse.statusCode,
|
||||||
|
request: streamedResponse.request,
|
||||||
|
headers: streamedResponse.headers,
|
||||||
|
isRedirect: streamedResponse.isRedirect,
|
||||||
|
persistentConnection: streamedResponse.persistentConnection,
|
||||||
|
reasonPhrase: streamedResponse.reasonPhrase,
|
||||||
|
),
|
||||||
|
stopwatch.elapsed,
|
||||||
|
null,
|
||||||
|
));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
onDone: () => cleanup(),
|
onDone: () => cleanup(),
|
||||||
|
Reference in New Issue
Block a user