123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201 |
- import 'dart:convert';
- import 'package:dio/dio.dart' as dio;
- import 'package:fis_common/http/http_error.dart';
- import 'package:fis_jsonrpc/encrpyt.dart';
- 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 {
- /// 默认超时时间
- // ignore: non_constant_identifier_names
- static int DEAULT_TIMEOUT = 15000;
- /// 请求加密配置
- static JsonRpcEncryptConfig requestEncryptConfig = JsonRpcEncryptConfig();
- /// 响应加密配置
- static JsonRpcEncryptConfig responseEncryptConfig = JsonRpcEncryptConfig();
- late int _timeout;
- late String _serviceName;
- /// 服务主机地址
- final String host;
- /// 自定义Http header
- final Map<String, String>? headers;
- /// 超时时间(ms)
- int get timeout => _timeout;
- /// 服务名称
- String get serviceName => _serviceName;
- /// 服务请求地址
- String get servicePath =>
- host.endsWith('/') ? "$host$serviceName" : "$host/$serviceName";
- JsonRpcClientBase(
- this.host,
- String serviceName, {
- this.headers,
- int? timeout,
- }) {
- _timeout = timeout ?? DEAULT_TIMEOUT;
- _serviceName = serviceName;
- }
- void setTimeout(int milliseconds) {}
- /// 设置服务名
- void setServiceName(String name) => _serviceName = name;
- /// 请求RPC method
- @protected
- Future<dynamic> 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<dynamic> _transmit(JsonRpcRequest request) async {
- var result;
- try {
- final req = await jsonRpcInterceptHost.onRequestTransmit(request);
- String package = jsonEncode(req.toJson());
- if (requestEncryptConfig.enable) {
- package = _encryptRequestPackage(package);
- }
- var response = await _postRequest(package);
- if (response == null) throw JsonRpcException(message: "Response Empty");
- if (response is String) {
- response = jsonDecode(response);
- }
- result = await _handleDecoded(response);
- } catch (e) {
- if (e is FHttpError)
- await _handleHttpRequestError(JsonRpcNetworkException(
- e.toString(),
- null,
- request.method,
- ));
- throw JsonRpcException(message: "Http error", data: e);
- }
- return result;
- }
- Future<dynamic> _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}.");
- }
- if (response.headers.containsKey("response_encrypt_mode")) {
- final resEncryptMode = response.headers["response_encrypt_mode"]!;
- // 解密响应包
- if (resEncryptMode.isNotEmpty && resEncryptMode.first.isNotEmpty) {
- final resPackage = _decryptResponsePackage(response.data);
- final resJsonMap = jsonDecode(resPackage);
- return resJsonMap;
- }
- }
- 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<dynamic> _handleHttpRequestError(JsonRpcNetworkException error) async {
- final res = await jsonRpcInterceptHost.onHttpRequestError(error);
- throw res;
- }
- Future<dynamic> _handleDecoded(Map<String, dynamic> 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;
- }
- String _encryptRequestPackage(String package) {
- final mode = requestEncryptConfig.encryptMode.toLowerCase();
- if (kIsWeb) {
- return package;
- }
- if (mode == "sm2") {
- // 使用国密2加密请求
- return JsonRpcEncryptUtils.sm2Encrypt(
- package,
- requestEncryptConfig.encryptKey,
- );
- }
- if (mode == "rsa") {
- // 使用RSA加密请求
- return JsonRpcEncryptUtils.rsaEncrypt(package);
- }
- return package;
- }
- String _decryptResponsePackage(String package) {
- final mode = responseEncryptConfig.encryptMode.toLowerCase();
- if (mode == "sm4") {
- // 使用国密4解密
- return JsonRpcEncryptUtils.sm4Decrypt(
- package,
- responseEncryptConfig.encryptKey,
- );
- }
- if (mode == "des") {
- // 使用DES解密
- // 截取前8位
- final key = responseEncryptConfig.encryptKey.substring(0, 8);
- return JsonRpcEncryptUtils.desDecrypt(package, key);
- }
- return package;
- }
- }
- abstract class JsonRpcRequestModelBase {
- /// 转成Json Map
- Map<String, dynamic> toJson();
- }
|