import 'dart:convert'; import 'dart:io'; import 'package:dio/dio.dart'; import 'package:gmalpha_flutter/commonModel/net/Api.dart'; import 'package:gmalpha_flutter/commonModel/toast/toast.dart'; const bool inProduction = const bool.fromEnvironment("dart.vm.product"); ///Http配置. class HttpConfig { /// constructor. HttpConfig({ this.status, this.code, this.msg, this.data, this.options, this.pem, this.pKCSPath, this.pKCSPwd, this.nativeCookie, }); /// BaseResp [String status]字段 key, 默认:status. String status; /// BaseResp [int code]字段 key, 默认:errorCode. String code; /// BaseResp [String msg]字段 key, 默认:errorMsg. String msg; /// BaseResp [T data]字段 key, 默认:data. String data; /// Options. BaseOptions options; /// 详细使用请查看dio官网 https://github.com/flutterchina/dio/blob/flutter/README-ZH.md#Https证书校验. /// PEM证书内容. String pem; /// 详细使用请查看dio官网 https://github.com/flutterchina/dio/blob/flutter/README-ZH.md#Https证书校验. /// PKCS12 证书路径. String pKCSPath; /// 详细使用请查看dio官网 https://github.com/flutterchina/dio/blob/flutter/README-ZH.md#Https证书校验. /// PKCS12 证书密码. String pKCSPwd; //缓存 Map nativeCookie; } /// 单例 DioUtil. /// debug模式下可以打印请求日志. DioUtil.openDebug(). /// dio详细使用请查看dio官网(https://github.com/flutterchina/dio). class DioUtil { static final DioUtil _instance = DioUtil._init(); static Dio _dio; /// BaseResp [String status]字段 key, 默认:status. String _statusKey = "status"; /// BaseResp [int code]字段 key, 默认:error = 0 代表成功. String _codeKey = "error"; /// BaseResp [String msg]字段 key, 默认:errorMsg. String _msgKey = "message"; /// BaseResp [T data]字段 key, 默认:data. String _dataKey = "data"; /// BaseResp [T data]字段 key, 默认:extra. String _extraKey = 'extra'; // BaseResp [T data]字段 key, 默认:user_type. String _userType = 'user_type'; /// Options. static BaseOptions _options = getDefOptions(); /// PEM证书内容. String _pem; /// PKCS12 证书路径. String _pKCSPath; /// PKCS12 证书密码. String _pKCSPwd; String _proxy = '172.30.9.117:8888'; static Map addHeadMap; /// 是否是debug模式. static bool _isDebug = !inProduction; static DioUtil getInstance() { return _instance; } factory DioUtil() { return _instance; } static var interceptor = InterceptorsWrapper(onRequest: (opt) { var headers = opt.headers; if (addHeadMap != null) { print("请求之前"); print("BASEURL!! ${opt.baseUrl}"); addHeadMap.forEach((k, v) { headers.putIfAbsent(k, () => v); print("HEADDD ${k} ${v}"); }); } }, onResponse: (response) { print("响应之前 response${response}"); }, onError: (e) { print("网络错误 $e message ${e.message}"); }); DioUtil._init() { _dio = new Dio(_options); _dio.interceptors.add(interceptor); } set addHead(Map map) { if (map != null) { addHeadMap = map; } } void setProxy(String proxy) { (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { client.findProxy = (url) { return 'PROXY $proxy'; }; }; } /// set Config. void setConfig(HttpConfig config) { _statusKey = config.status ?? _statusKey; _codeKey = config.code ?? _codeKey; _msgKey = config.msg ?? _msgKey; _dataKey = config.data ?? _dataKey; _mergeOption(config.options); _mergeNativeCookie(config); _pem = config.pem ?? _pem; if (_dio != null) { _dio.options = _options; // (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (client) { // client.findProxy = (url) { // return _isDebug ? 'PROXY $_proxy' : 'DIRECT'; // }; // }; if (_pem != null) { // httpClientAdapter (_dio.httpClientAdapter as DefaultHttpClientAdapter) .onHttpClientCreate = (client) { client.badCertificateCallback = (X509Certificate cert, String host, int port) { if (cert.pem == _pem) { // 证书一致,则放行 return true; } return false; }; }; } if (_pKCSPath != null) { (_dio.httpClientAdapter as DefaultHttpClientAdapter) .onHttpClientCreate = (client) { SecurityContext sc = new SecurityContext(); //file为证书路径 sc.setTrustedCertificates(_pKCSPath, password: _pKCSPwd); HttpClient httpClient = new HttpClient(context: sc); return httpClient; }; } } } /* * get请求 */ Future get(url, {data, options, cancelToken}) async { Response response; print("GET===> URL:$url data:$data"); try { response = await _dio.get(url, queryParameters: data, options: options, cancelToken: cancelToken); // print('get success---------${response.statusCode}'); // print('get success---------${response.data}'); _printHttpLog(response); // response.data; 响应体 // response.headers; 响应头 // response.request; 请求体 // response.statusCode; 状态码 } on DioError catch (e) { print('get error---------$e formatError'); formatError(e); } return response; } /* * post请求 */ Future post(url, {data, options, cancelToken}) async { Response response; print("POST===> URL:$url data:$data"); try { response = await _dio.post(url, data: FormData.from(data), options: options, cancelToken: cancelToken); print('post success---------${response.statusCode} ${response.data}'); } on DioError catch (e) { print('post error---------$e message${e.message}'); formatError(e); } return response; } /* * 下载文件 */ downloadFile(urlPath, savePath) async { Response response; try { response = await _dio.download(urlPath, savePath, onReceiveProgress: (int count, int total) { //进度 print("$count $total"); }); print('downloadFile success---------${response.data}'); } on DioError catch (e) { print('downloadFile error---------$e formatError'); formatError(e); } return response.data; } void formatError(DioError e) { String reason = ""; if (e.type == DioErrorType.CONNECT_TIMEOUT) { // It occurs when url is opened timeout. print("连接超时"); reason = "连接超时 ${e.message}"; } else if (e.type == DioErrorType.SEND_TIMEOUT) { // It occurs when url is sent timeout. print("请求超时"); reason = "请求超时 ${e.message}"; } else if (e.type == DioErrorType.RECEIVE_TIMEOUT) { //It occurs when receiving timeout print("响应超时"); reason = "响应超时 ${e.message}"; } else if (e.type == DioErrorType.RESPONSE) { // When the server response, but with a incorrect status, such as 404, 503... print("出现异常"); reason = "出现异常 ${e.message}"; } else if (e.type == DioErrorType.CANCEL) { // When the request is cancelled, dio will throw a error with this type. print("请求取消"); reason = "请求取消 ${e.message}"; } else { //DEFAULT Default error type, Some other Error. In this case, you can read the DioError.error if it is not null. print("未知错误"); reason = "未知错误 ${e.message}"; } throw HttpException(reason); } Future download( String urlPath, savePath, { CancelToken cancelToken, data, Options options, }) { return _dio.download(urlPath, savePath, cancelToken: cancelToken, data: data, options: options); } /// check Options. Options _checkOptions(method, options) { if (options == null) { options = new Options(); } options.method = method; return options; } /// merge Option. void _mergeOption(BaseOptions opt) { _options.method = opt.method ?? _options.method; _options.headers = (new Map.from(_options.headers))..addAll(opt.headers); _options.baseUrl = opt.baseUrl ?? _options.baseUrl; _options.connectTimeout = opt.connectTimeout ?? _options.connectTimeout; _options.receiveTimeout = opt.receiveTimeout ?? _options.receiveTimeout; _options.responseType = opt.responseType ?? _options.responseType; _options.extra = (new Map.from(_options.extra))..addAll(opt.extra); _options.contentType = opt.contentType ?? _options.contentType; _options.validateStatus = opt.validateStatus ?? _options.validateStatus; _options.followRedirects = opt.followRedirects ?? _options.followRedirects; } void _mergeNativeCookie(HttpConfig config) { //合并native cookie if (config.nativeCookie == null) { return; } if (_options.headers == null) { _options.headers = Map(); } Map headers = _options.headers; headers['Cookie'] = config.nativeCookie['Cookie']; _options.headers = headers; print('cookie---------'); print(_options.headers); } void setCookie(String cookie) { if (_options.headers == null) { _options.headers = Map(); } Map headers = _options.headers; headers['Cookie'] = cookie; _options.headers = headers; print('cookie---------'); print(_options.headers); } /// print Http Log. void _printHttpLog(Response response) { if (!_isDebug) { return; } try { print("----------------Http Log----------------" + "\n[statusCode]: " + response.statusCode.toString() + "\n[request ]: " + _getOptionsStr(response.request)); _printDataStr("reqdata ", response.request.data); _printDataStr("response", response.data); } catch (ex) { print("Http Log" + " error......"); } } /// get Options Str. String _getOptionsStr(Options request) { return "method: " + request.method; } /// print Data Str. void _printDataStr(String tag, Object value) { String da = value.toString(); while (da.isNotEmpty) { if (da.length > 512) { print("[$tag ]: " + da.substring(0, 512)); da = da.substring(512, da.length); } else { print("[$tag ]: " + da); da = ""; } } } /// get dio. Dio getDio() { return _dio; } /// create new dio. static Dio createNewDio([Options options]) { Dio dio = new Dio(); return dio; } /// get Def Options. static BaseOptions getDefOptions() { BaseOptions options = BaseOptions(); options.connectTimeout = 10 * 1000; options.receiveTimeout = 20 * 1000; // options.contentType = ContentType.parse('application/x-www-form-urlencoded'); options.contentType = ContentType.json; options.responseType = ResponseType.plain; options.baseUrl = APP_HOST_DEBUG + "/"; Map headers = Map(); headers['Accept'] = 'application/json'; headers['version'] = '1.0.0'; options.headers = headers; return options; } }