LCOV - code coverage report
Current view: top level - Users/duwen/Documents/code/dio/dio/lib/src/adapters - io_adapter.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 59 65 90.8 %
Date: 2021-11-28 14:37: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 = HttpClient? 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           6 :   Future<ResponseBody> fetch(
      26             :     RequestOptions options,
      27             :     Stream<Uint8List>? requestStream,
      28             :     Future? cancelFuture,
      29             :   ) async {
      30           6 :     if (_closed) {
      31           0 :       throw Exception(
      32             :           "Can't establish connection after [HttpClientAdapter] closed!");
      33             :     }
      34          12 :     var _httpClient = _configHttpClient(cancelFuture, options.connectTimeout);
      35          18 :     var reqFuture = _httpClient.openUrl(options.method, options.uri);
      36             : 
      37           1 :     void _throwConnectingTimeout() {
      38           1 :       throw DioError(
      39             :         requestOptions: options,
      40           2 :         error: 'Connecting timed out [${options.connectTimeout}ms]',
      41             :         type: DioErrorType.connectTimeout,
      42             :       );
      43             :     }
      44             : 
      45             :     late HttpClientRequest request;
      46             :     int timePassed = 0;
      47             :     try {
      48          12 :       if (options.connectTimeout > 0) {
      49           4 :         var start = DateTime.now().millisecond;
      50           2 :         request = await reqFuture
      51           6 :             .timeout(Duration(milliseconds: options.connectTimeout));
      52           6 :         timePassed = DateTime.now().millisecond - start;
      53             :       } else {
      54           4 :         request = await reqFuture;
      55             :       }
      56             : 
      57             :       //Set Headers
      58          12 :       options.headers.forEach((k, v) {
      59           6 :         if (v != null) request.headers.set(k, '$v');
      60             :       });
      61           2 :     } on SocketException catch (e) {
      62           4 :       if (e.message.contains('timed out')) {
      63             :         _throwConnectingTimeout();
      64             :       }
      65             :       rethrow;
      66           0 :     } on TimeoutException {
      67             :       _throwConnectingTimeout();
      68             :     }
      69             : 
      70          10 :     request.followRedirects = options.followRedirects;
      71          10 :     request.maxRedirects = options.maxRedirects;
      72             : 
      73             :     if (requestStream != null) {
      74             :       // Transform the request data
      75           4 :       await request.addStream(requestStream);
      76             :     }
      77             :     // [receiveTimeout] represents a timeout during data transfer! That is to say the
      78             :     // client has connected to the server, and the server starts to send data to the client.
      79             :     // So, we should use connectTimeout.
      80          10 :     int responseTimeout = options.connectTimeout - timePassed;
      81           5 :     var future = request.close();
      82           5 :     if (responseTimeout > 0) {
      83           4 :       future = future.timeout(Duration(milliseconds: responseTimeout));
      84             :     }
      85             :     late HttpClientResponse responseStream;
      86             :     try {
      87           5 :       responseStream = await future;
      88           1 :     } on TimeoutException {
      89             :       _throwConnectingTimeout();
      90             :     }
      91             : 
      92             :     var stream =
      93          10 :         responseStream.transform<Uint8List>(StreamTransformer.fromHandlers(
      94           4 :       handleData: (data, sink) {
      95           8 :         sink.add(Uint8List.fromList(data));
      96             :       },
      97             :     ));
      98             : 
      99           5 :     var headers = <String, List<String>>{};
     100          15 :     responseStream.headers.forEach((key, values) {
     101           5 :       headers[key] = values;
     102             :     });
     103           5 :     return ResponseBody(
     104             :       stream,
     105           5 :       responseStream.statusCode,
     106             :       headers: headers,
     107             :       isRedirect:
     108          15 :           responseStream.isRedirect || responseStream.redirects.isNotEmpty,
     109           5 :       redirects: responseStream.redirects
     110          10 :           .map((e) => RedirectRecord(e.statusCode, e.method, e.location))
     111           5 :           .toList(),
     112           5 :       statusMessage: responseStream.reasonPhrase,
     113             :     );
     114             :   }
     115             : 
     116           6 :   HttpClient _configHttpClient(Future? cancelFuture, int connectionTimeout) {
     117           6 :     var _connectionTimeout = connectionTimeout > 0
     118           2 :         ? Duration(milliseconds: connectionTimeout)
     119             :         : null;
     120             : 
     121             :     if (cancelFuture != null) {
     122           2 :       var _httpClient = HttpClient();
     123           2 :       _httpClient.userAgent = null;
     124           2 :       if (onHttpClientCreate != null) {
     125             :         //user can return a HttpClient instance
     126           0 :         _httpClient = onHttpClientCreate!(_httpClient) ?? _httpClient;
     127             :       }
     128           4 :       _httpClient.idleTimeout = Duration(seconds: 0);
     129           4 :       cancelFuture.whenComplete(() {
     130           8 :         Future.delayed(Duration(seconds: 0)).then((e) {
     131             :           try {
     132           2 :             _httpClient.close(force: true);
     133             :           } catch (e) {
     134             :             //...
     135             :           }
     136             :         });
     137             :       });
     138           2 :       return _httpClient..connectionTimeout = _connectionTimeout;
     139             :     }
     140           5 :     if (_defaultHttpClient == null) {
     141          10 :       _defaultHttpClient = HttpClient();
     142          15 :       _defaultHttpClient!.idleTimeout = Duration(seconds: 3);
     143           5 :       if (onHttpClientCreate != null) {
     144             :         //user can return a HttpClient instance
     145           0 :         _defaultHttpClient =
     146           0 :             onHttpClientCreate!(_defaultHttpClient!) ?? _defaultHttpClient;
     147             :       }
     148          10 :       _defaultHttpClient!.connectionTimeout = _connectionTimeout;
     149             :     }
     150           5 :     return _defaultHttpClient!;
     151             :   }
     152             : 
     153           1 :   @override
     154             :   void close({bool force = false}) {
     155           2 :     _closed = _closed;
     156           1 :     _defaultHttpClient?.close(force: force);
     157             :   }
     158             : }

Generated by: LCOV version 1.14