import 'dart:convert'; import 'package:dio/dio.dart' as dio; import 'package:flutter/foundation.dart'; import 'exception.dart'; import 'http_pool.dart'; import 'interceptor.dart'; import 'request.dart'; // ignore: unused_element const _C_DIO_FUTURE_ERR_MSG = "Future already completed"; const _C_DIO_FUTURE_ERR_KEYWORDS = "browser_adapter"; /// JSON-RPC Client 基类 class JsonRpcClientBase { /// 服务主机地址 final String host; late String _serviceName; /// 服务名称 String get serviceName => _serviceName; /// 自定义Http header final Map? headers; /// 超时时间(ms) final int? timeout; /// 服务请求地址 String get servicePath => host.endsWith('/') ? "$host$serviceName" : "$host/$serviceName"; JsonRpcClientBase( this.host, String serviceName, { this.headers, this.timeout, }) { _serviceName = serviceName; } /// 设置服务名 void setServiceName(String name) => _serviceName = name; /// 请求RPC method @protected Future call(String method, [args]) async { var request = JsonRpcRequest(method, args); return _transmit(request); } /// 通知 RPC method @protected void notify(String method, [args]) { var request = JsonRpcRequest(method, args, notify: true); _transmit(request); } Future _transmit(JsonRpcRequest request) async { final req = await jsonRpcInterceptHost.onRequestTransmit(request); String package = jsonEncode(req.toJson()); var response = await _postRequest(package); if (response == null) throw JsonRpcException(message: "Response Empty"); var result = await _handleDecoded(response); return result; } Future _postRequest(String package) async { try { final httpClient = jrpcHttpPool.getClient(this.host, timeout: this.timeout, headers: this.headers); var response = await httpClient.post('/${this.serviceName}', data: package); if (response.statusCode != 200) { throw JsonRpcException( message: "Http error.Status coder: ${response.statusCode}."); } return response.data; } on dio.DioError catch (e) { throw JsonRpcException(message: "Http error", data: e); } on StateError catch (e) { if (e.message == _C_DIO_FUTURE_ERR_MSG) { if (e.stackTrace != null && e.stackTrace.toString().contains(_C_DIO_FUTURE_ERR_KEYWORDS)) { // don't rethrow } } } } Future _handleDecoded(Map response) async { final res = await jsonRpcInterceptHost.onResponse(response); if (res.containsKey('error')) { var error = JsonRpcServerError.fromJson(res['error']); error = await jsonRpcInterceptHost.onResponseError(error); throw error; } var result = res['result']; result = await jsonRpcInterceptHost.onResponseResult(result); return result; } } abstract class JsonRpcRequestModelBase { /// 转成Json Map Map toJson(); }