client_base.dart 3.0 KB

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