client_base.dart 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import 'dart:convert';
  2. import 'package:dio/dio.dart' as dio;
  3. import 'package:fis_common/http/http_error.dart';
  4. import 'package:flutter/foundation.dart';
  5. import 'exception.dart';
  6. import 'http_pool.dart';
  7. import 'interceptor.dart';
  8. import 'request.dart';
  9. // ignore: unused_element
  10. const _C_DIO_FUTURE_ERR_MSG = "Future already completed";
  11. const _C_DIO_FUTURE_ERR_KEYWORDS = "browser_adapter";
  12. /// JSON-RPC Client 基类
  13. class JsonRpcClientBase {
  14. /// 默认超时时间
  15. // ignore: non_constant_identifier_names
  16. static int DEAULT_TIMEOUT = 15000;
  17. late int _timeout;
  18. late String _serviceName;
  19. /// 服务主机地址
  20. final String host;
  21. /// 自定义Http header
  22. final Map<String, String>? headers;
  23. /// 超时时间(ms)
  24. int get timeout => _timeout;
  25. /// 服务名称
  26. String get serviceName => _serviceName;
  27. /// 服务请求地址
  28. String get servicePath =>
  29. host.endsWith('/') ? "$host$serviceName" : "$host/$serviceName";
  30. JsonRpcClientBase(
  31. this.host,
  32. String serviceName, {
  33. this.headers,
  34. int? timeout,
  35. }) {
  36. _timeout = timeout ?? DEAULT_TIMEOUT;
  37. _serviceName = serviceName;
  38. }
  39. void setTimeout(int milliseconds) {}
  40. /// 设置服务名
  41. void setServiceName(String name) => _serviceName = name;
  42. /// 请求RPC method
  43. @protected
  44. Future<dynamic> call(String method, [args]) async {
  45. var request = JsonRpcRequest(method, args);
  46. return _transmit(request);
  47. }
  48. /// 通知 RPC method
  49. @protected
  50. void notify(String method, [args]) {
  51. var request = JsonRpcRequest(method, args, notify: true);
  52. _transmit(request);
  53. }
  54. Future<dynamic> _transmit(JsonRpcRequest request) async {
  55. var result;
  56. try {
  57. final req = await jsonRpcInterceptHost.onRequestTransmit(request);
  58. String package = jsonEncode(req.toJson());
  59. var response = await _postRequest(package);
  60. if (response == null) throw JsonRpcException(message: "Response Empty");
  61. result = await _handleDecoded(response);
  62. } catch (e) {
  63. if (e is FHttpError)
  64. await _handleHttpRequestError(JsonRpcNetworkException(e.toString()));
  65. throw JsonRpcException(message: "Http error", data: e);
  66. }
  67. return result;
  68. }
  69. Future<dynamic> _postRequest(String package) async {
  70. try {
  71. final httpClient = jrpcHttpPool.getClient(
  72. this.host,
  73. timeout: this.timeout,
  74. headers: this.headers,
  75. );
  76. var response =
  77. await httpClient.post('/${this.serviceName}', data: package);
  78. if (response.statusCode != 200) {
  79. throw JsonRpcException(
  80. message: "Http error.Status coder: ${response.statusCode}.");
  81. }
  82. return response.data;
  83. } on dio.DioError catch (e) {
  84. throw JsonRpcException(message: "Http error", data: e);
  85. } on StateError catch (e) {
  86. if (e.message == _C_DIO_FUTURE_ERR_MSG) {
  87. if (e.stackTrace != null &&
  88. e.stackTrace.toString().contains(_C_DIO_FUTURE_ERR_KEYWORDS)) {
  89. // don't rethrow
  90. }
  91. }
  92. }
  93. }
  94. Future<dynamic> _handleHttpRequestError(JsonRpcNetworkException error) async {
  95. final res = await jsonRpcInterceptHost.onHttpRequestError(error);
  96. throw res;
  97. }
  98. Future<dynamic> _handleDecoded(Map<String, dynamic> response) async {
  99. final res = await jsonRpcInterceptHost.onResponse(response);
  100. if (res.containsKey('error')) {
  101. var error = JsonRpcServerError.fromJson(res['error']);
  102. error = await jsonRpcInterceptHost.onResponseError(error);
  103. throw error;
  104. }
  105. var result = res['result'];
  106. result = await jsonRpcInterceptHost.onResponseResult(result);
  107. return result;
  108. }
  109. }
  110. abstract class JsonRpcRequestModelBase {
  111. /// 转成Json Map
  112. Map<String, dynamic> toJson();
  113. }