LCOV - code coverage report
Current view: top level - src/adapters - io_adapter.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 48 58 82.8 %
Date: 2020-02-27 17:47:50 Functions: 0 0 -

          Line data    Source code
       1             : import 'dart:async';
       2             : import 'dart:io';
       3             : import 'dart:typed_data';
       4             : import '../adapter.dart';
       5             : import '../options.dart';
       6             : import '../dio_error.dart';
       7             : import '../redirect_record.dart';
       8             : 
       9             : typedef OnHttpClientCreate = dynamic Function(HttpClient client);
      10             : 
      11           0 : HttpClientAdapter createAdapter() => DefaultHttpClientAdapter();
      12             : 
      13             : /// The default HttpClientAdapter for Dio.
      14             : class DefaultHttpClientAdapter implements HttpClientAdapter {
      15             :   /// [Dio] will create HttpClient when it is needed.
      16             :   /// If [onHttpClientCreate] is provided, [Dio] will call
      17             :   /// it when a HttpClient created.
      18             :   OnHttpClientCreate onHttpClientCreate;
      19             : 
      20             :   HttpClient _defaultHttpClient;
      21             : 
      22             :   bool _closed = false;
      23             : 
      24             :   @override
      25           4 :   Future<ResponseBody> fetch(
      26             :     RequestOptions options,
      27             :     Stream<List<int>> requestStream,
      28             :     Future cancelFuture,
      29             :   ) async {
      30           4 :     if (_closed) {
      31           0 :       throw Exception(
      32             :           "Can't establish connection after [HttpClientAdapter] closed!");
      33             :     }
      34           8 :     var _httpClient = _configHttpClient(cancelFuture, options.connectTimeout);
      35          12 :     Future requestFuture = _httpClient.openUrl(options.method, options.uri);
      36             : 
      37           0 :     void _throwConnectingTimeout() {
      38           0 :       throw DioError(
      39             :         request: options,
      40           0 :         error: 'Connecting timed out [${options.connectTimeout}ms]',
      41             :         type: DioErrorType.CONNECT_TIMEOUT,
      42             :       );
      43             :     }
      44             : 
      45             :     HttpClientRequest request;
      46             :     try {
      47           4 :       request = await requestFuture;
      48             :       //Set Headers
      49           7 :       options.headers.forEach((k, v) => request.headers.set(k, v));
      50           2 :     } on SocketException catch (e) {
      51           4 :       if (e.message.contains('timed out')) _throwConnectingTimeout();
      52             :       rethrow;
      53             :     }
      54             : 
      55           4 :     request.followRedirects = options.followRedirects;
      56           4 :     request.maxRedirects = options.maxRedirects;
      57             : 
      58           4 :     if (options.method != 'GET' && requestStream != null) {
      59             :       // Transform the request data
      60           2 :       await request.addStream(requestStream);
      61             :     }
      62           2 :     Future future = request.close();
      63           4 :     if (options.connectTimeout > 0) {
      64           3 :       future = future.timeout(Duration(milliseconds: options.connectTimeout));
      65             :     }
      66             :     HttpClientResponse responseStream;
      67             :     try {
      68           2 :       responseStream = await future;
      69           0 :     } on TimeoutException {
      70           0 :       _throwConnectingTimeout();
      71             :     }
      72             : 
      73             :     // https://github.com/dart-lang/co19/issues/383
      74             :     var stream =
      75           4 :         responseStream.transform<Uint8List>(StreamTransformer.fromHandlers(
      76           2 :       handleData: (data, sink) {
      77           4 :         sink.add(Uint8List.fromList(data));
      78             :       },
      79             :     ));
      80             : 
      81           2 :     var headers = <String, List<String>>{};
      82           6 :     responseStream.headers.forEach((key, values) {
      83           2 :       headers[key] = values;
      84             :     });
      85           2 :     return ResponseBody(
      86             :       stream,
      87           2 :       responseStream.statusCode,
      88             :       headers: headers,
      89           6 :       isRedirect: responseStream.isRedirect||responseStream.redirects.isNotEmpty,
      90           2 :       redirects: responseStream.redirects
      91           7 :           .map((e) => RedirectRecord(e.statusCode, e.method, e.location))
      92           2 :           .toList(),
      93           2 :       statusMessage: responseStream.reasonPhrase,
      94             :     );
      95             :   }
      96             : 
      97           4 :   HttpClient _configHttpClient(Future cancelFuture, int connectionTimeout) {
      98           4 :     var _connectionTimeout = connectionTimeout > 0
      99           1 :         ? Duration(milliseconds: connectionTimeout)
     100             :         : null;
     101             :     if (cancelFuture != null) {
     102           2 :       var _httpClient = HttpClient();
     103           2 :       if (onHttpClientCreate != null) {
     104             :         //user can return a HttpClient instance
     105           0 :         _httpClient = onHttpClientCreate(_httpClient) ?? _httpClient;
     106             :       }
     107           4 :       _httpClient.idleTimeout = Duration(seconds: 0);
     108           4 :       cancelFuture.whenComplete(() {
     109           8 :         Future.delayed(Duration(seconds: 0)).then((e) {
     110             :           try {
     111           2 :             _httpClient.close(force: true);
     112             :           } catch (e) {
     113             :             //...
     114             :           }
     115             :         });
     116             :       });
     117           2 :       return _httpClient..connectionTimeout = _connectionTimeout;
     118           3 :     } else if (_defaultHttpClient == null) {
     119           6 :       _defaultHttpClient = HttpClient();
     120           9 :       _defaultHttpClient.idleTimeout = Duration(seconds: 3);
     121           3 :       if (onHttpClientCreate != null) {
     122             :         //user can return a HttpClient instance
     123           0 :         _defaultHttpClient =
     124           0 :             onHttpClientCreate(_defaultHttpClient) ?? _defaultHttpClient;
     125             :       }
     126           6 :       _defaultHttpClient.connectionTimeout = _connectionTimeout;
     127             :     }
     128           3 :     return _defaultHttpClient;
     129             :   }
     130             : 
     131           1 :   @override
     132             :   void close({bool force = false}) {
     133           2 :     _closed = _closed;
     134           1 :     _defaultHttpClient?.close(force: force);
     135             :   }
     136             : }

Generated by: LCOV version 1.14