dart-lang / http

A composable API for making HTTP requests in Dart.
https://pub.dev/packages/http
BSD 3-Clause "New" or "Revised" License
1.02k stars 354 forks source link

Abort or cancel multipart request #567

Open intoxicated opened 3 years ago

intoxicated commented 3 years ago

It seems like neither abort or cancel method are provided from http package, though there is abort in dart:io package for httpClientRequest.

Is it safe to call close on client for multipart request?

class MultipartRequest extends http.MultipartRequest {
  /// Creates a new [MultipartRequest].
  var client = http.Client();

  MultipartRequest(
    String method,
    Uri url, {
    this.onProgress,
  }) : super(method, url);

  final void Function(int bytes, int totalBytes) onProgress;

  void cancel() => client.close();

  @override
  Future<http.StreamedResponse> send() async {
    try {
      var response = await client.send(this);
      var stream = onDone(response.stream, client.close);
      return http.StreamedResponse(
        http.ByteStream(stream),
        response.statusCode,
        contentLength: response.contentLength,
        request: response.request,
        headers: response.headers,
        isRedirect: response.isRedirect,
        persistentConnection: response.persistentConnection,
        reasonPhrase: response.reasonPhrase,
      );
    } catch (_) {
      client.close();
      rethrow;
    }
  }

  Stream<T> onDone<T>(Stream<T> stream, void Function() onDone) =>
      stream.transform(StreamTransformer.fromHandlers(handleDone: (sink) {
        sink.close();
        onDone();
      }));

  /// Freezes all mutable fields and returns a single-subscription [ByteStream]
  /// that will emit the request body.
  @override
  http.ByteStream finalize() {
    final byteStream = super.finalize();
    if (onProgress == null) return byteStream;

    final total = contentLength;
    var bytes = 0;

    final t = StreamTransformer.fromHandlers(
      handleData: (List<int> data, EventSink<List<int>> sink) {
        bytes += data.length;
        if (onProgress != null) onProgress(bytes, total);
        sink.add(data);
      },
    );
    final stream = byteStream.transform(t);
    return http.ByteStream(stream);
  }
}

I saw some error were thrown (can't reproduce again but it was complaining about the connection was closed, it had not been reached content length the request claimed to fulfill).

natebosch commented 3 years ago

Is it safe to call close on client for multipart request?

I think it should be.

it was complaining about the connection was closed, it had not been reached content length the request claimed to fulfill

Was that server side or client side?

It seems like neither abort or cancel method are provided from http package

Not currently. Work is tracked in https://github.com/dart-lang/http/issues/424