Browse Source

update http wrap, 返回系统级 status

JamesZhang 1 tháng trước cách đây
mục cha
commit
3c7787334f
1 tập tin đã thay đổi với 63 bổ sung và 27 xóa
  1. 63 27
      lib/network/httpClientWrap.dart

+ 63 - 27
lib/network/httpClientWrap.dart

@@ -2,19 +2,22 @@ import 'dart:async';
 import 'dart:convert';
 import 'dart:convert';
 import 'dart:io';
 import 'dart:io';
 
 
-
-enum HttpClientStatus {
-  idle,
-  connecting,
-  connected,
-  disconnected,
-  error,
-}
+enum HttpClientStatus { idle, connecting, connected, disconnected, error }
 
 
 typedef HttpClientStatusHandler = void Function(HttpClientStatus status);
 typedef HttpClientStatusHandler = void Function(HttpClientStatus status);
 
 
+/// 单次请求的 HTTP 状态与解码正文,不共享并发请求状态。
+class HttpClientWrapResponse {
+  final int statusCode;
+  final dynamic data;
+
+  const HttpClientWrapResponse({required this.statusCode, required this.data});
+}
+
 class HttpClientWrap {
 class HttpClientWrap {
   final Duration retryInterval;
   final Duration retryInterval;
+  final Duration? connectionTimeout;
+  final Duration? receiveTimeout;
   final Map<String, String>? defaultHeaders;
   final Map<String, String>? defaultHeaders;
 
 
   HttpClient? _httpClient;
   HttpClient? _httpClient;
@@ -28,20 +31,34 @@ class HttpClientWrap {
   HttpClientWrap({
   HttpClientWrap({
     this.retryInterval = const Duration(seconds: 5),
     this.retryInterval = const Duration(seconds: 5),
     this.defaultHeaders,
     this.defaultHeaders,
+    this.connectionTimeout,
+    this.receiveTimeout,
   });
   });
 
 
   /// 发送 GET 请求
   /// 发送 GET 请求
-  Future<dynamic> get(String url, {Map<String, String>? headers, dynamic body}) async {
+  Future<dynamic> get(
+    String url, {
+    Map<String, String>? headers,
+    dynamic body,
+  }) async {
     return _sendRequest(url, 'GET', headers: headers, body: body);
     return _sendRequest(url, 'GET', headers: headers, body: body);
   }
   }
 
 
   /// 发送 POST 请求
   /// 发送 POST 请求
-  Future<dynamic> post(String url, {Map<String, String>? headers, dynamic body}) async {
+  Future<dynamic> post(
+    String url, {
+    Map<String, String>? headers,
+    dynamic body,
+  }) async {
     return _sendRequest(url, 'POST', headers: headers, body: body);
     return _sendRequest(url, 'POST', headers: headers, body: body);
   }
   }
 
 
   /// 发送 PUT 请求
   /// 发送 PUT 请求
-  Future<dynamic> put(String url, {Map<String, String>? headers, dynamic body}) async {
+  Future<dynamic> put(
+    String url, {
+    Map<String, String>? headers,
+    dynamic body,
+  }) async {
     return _sendRequest(url, 'PUT', headers: headers, body: body);
     return _sendRequest(url, 'PUT', headers: headers, body: body);
   }
   }
 
 
@@ -51,20 +68,29 @@ class HttpClientWrap {
   }
   }
 
 
   Future<dynamic> _sendRequest(
   Future<dynamic> _sendRequest(
-      String url,
-      String method, {
-        Map<String, String>? headers,
-        dynamic body,
-      }) async {
+    String url,
+    String method, {
+    Map<String, String>? headers,
+    dynamic body,
+  }) async {
+    return (await request(url, method, headers: headers, body: body)).data;
+  }
+
+  /// 返回 HTTP 状态与正文;旧 get/post/put/delete 仍仅返回正文。
+  Future<HttpClientWrapResponse> request(
+    String url,
+    String method, {
+    Map<String, String>? headers,
+    dynamic body,
+  }) async {
     if (_disposed) {
     if (_disposed) {
       throw StateError('HTTP Client has been disposed');
       throw StateError('HTTP Client has been disposed');
     }
     }
 
 
     _updateStatus(HttpClientStatus.connecting);
     _updateStatus(HttpClientStatus.connecting);
-    _httpClient ??= HttpClient();
+    _httpClient ??= HttpClient()..connectionTimeout = connectionTimeout;
 
 
     try {
     try {
-
       late final Uri uri;
       late final Uri uri;
       if ((method == 'GET') && (body != null)) {
       if ((method == 'GET') && (body != null)) {
         // queryParameters Map value 只接受 String 和 List<String> 两种类型
         // queryParameters Map value 只接受 String 和 List<String> 两种类型
@@ -82,21 +108,20 @@ class HttpClientWrap {
           body.forEach((key, value) {
           body.forEach((key, value) {
             if (value is Iterable) {
             if (value is Iterable) {
               // 多值:转成 List<String>
               // 多值:转成 List<String>
-              queryParams[key.toString()] = value.map((v) => v.toString()).toList();
+              queryParams[key.toString()] = value
+                  .map((v) => v.toString())
+                  .toList();
             } else {
             } else {
               // 单值:转成 String
               // 单值:转成 String
               queryParams[key.toString()] = value.toString();
               queryParams[key.toString()] = value.toString();
             }
             }
           });
           });
         }
         }
-        uri = Uri.parse(url).replace(
-          queryParameters: queryParams,
-        );
+        uri = Uri.parse(url).replace(queryParameters: queryParams);
 
 
         // uri = Uri.parse(url).replace(
         // uri = Uri.parse(url).replace(
         //   queryParameters: body,
         //   queryParameters: body,
         // );
         // );
-
       } else {
       } else {
         uri = Uri.parse(url);
         uri = Uri.parse(url);
       }
       }
@@ -118,11 +143,20 @@ class HttpClientWrap {
         }
         }
       }
       }
 
 
-      final response = await request.close();
+      final responseFuture = request.close();
+      final timeout = receiveTimeout;
+      final response = await (timeout == null
+          ? responseFuture
+          : responseFuture.timeout(timeout));
       _updateStatus(HttpClientStatus.connected);
       _updateStatus(HttpClientStatus.connected);
 
 
       // 处理响应
       // 处理响应
-      final responseBody = await response.transform(utf8.decoder).join();
+      final responseStream = response.transform(utf8.decoder);
+      final responseBody =
+          await (timeout == null
+                  ? responseStream
+                  : responseStream.timeout(timeout))
+              .join();
       dynamic decodedResponse;
       dynamic decodedResponse;
 
 
       try {
       try {
@@ -134,8 +168,10 @@ class HttpClientWrap {
       // Log.d('get response: $decodedResponse');
       // Log.d('get response: $decodedResponse');
 
 
       _updateStatus(HttpClientStatus.idle);
       _updateStatus(HttpClientStatus.idle);
-      return decodedResponse; // 直接返回响应数据
-
+      return HttpClientWrapResponse(
+        statusCode: response.statusCode,
+        data: decodedResponse,
+      );
     } catch (e) {
     } catch (e) {
       _handleError(e);
       _handleError(e);
       // _scheduleRetry();
       // _scheduleRetry();