DefaultTopApiClient.cs 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. using System.IO.Compression;
  2. using System.Net;
  3. using System.Net.Http.Headers;
  4. using System.Net.Security;
  5. using System.Text;
  6. using System.Web;
  7. using Topsdk.Util;
  8. namespace Topsdk.Top;
  9. public class DefaultTopApiClient: AbstractTopApiClient
  10. {
  11. protected HttpClient _client;
  12. public DefaultTopApiClient(string appkey, string appSecret, string serverUrl)
  13. {
  14. if (string.IsNullOrWhiteSpace(appkey))
  15. {
  16. throw new ArgumentNullException(nameof(appkey));
  17. }
  18. if (string.IsNullOrWhiteSpace(appSecret))
  19. {
  20. throw new ArgumentNullException(nameof(appSecret));
  21. }
  22. if (string.IsNullOrWhiteSpace(serverUrl))
  23. {
  24. throw new ArgumentNullException(nameof(serverUrl));
  25. }
  26. this.appkey = appkey;
  27. this.appSecret = appSecret;
  28. this.serverUrl = serverUrl;
  29. Init();
  30. }
  31. public DefaultTopApiClient(string appkey, string appSecret, string serverUrl, long connectTimeOut, long totalTimeout)
  32. : this(appkey, appSecret, serverUrl)
  33. {
  34. this.connectTimeOut = connectTimeOut;
  35. this.totalTimeout = totalTimeout;
  36. Init();
  37. }
  38. public DefaultTopApiClient(string appkey, string appSecret, string serverUrl, long connectTimeOut, long totalTimeout, bool ignoreSSLCheck)
  39. : this(appkey, appSecret, serverUrl,connectTimeOut, totalTimeout)
  40. {
  41. this.ignoreSsl = ignoreSSLCheck;
  42. Init();
  43. }
  44. public DefaultTopApiClient(string appkey, string appSecret, string serverUrl, long connectTimeOut, long totalTimeout, bool ignoreSSLCheck,IWebProxy proxy)
  45. : this(appkey, appSecret, serverUrl,connectTimeOut, totalTimeout,ignoreSSLCheck)
  46. {
  47. this.proxy = proxy;
  48. Init();
  49. }
  50. public override void Init()
  51. {
  52. var handler = new SocketsHttpHandler()
  53. {
  54. ConnectTimeout = TimeSpan.FromMilliseconds(this.ConnectTimeOut),
  55. PooledConnectionLifetime = TimeSpan.FromMinutes(5)
  56. };
  57. if (proxy != null)
  58. {
  59. handler.Proxy = this.Proxy;
  60. handler.UseProxy = true;
  61. }
  62. if (ignoreSsl)
  63. {
  64. handler.SslOptions = new SslClientAuthenticationOptions()
  65. {
  66. RemoteCertificateValidationCallback = (sender, certificate, chain, errors) => true,
  67. };
  68. }
  69. _client = new HttpClient(handler)
  70. {
  71. Timeout = TimeSpan.FromMilliseconds(TotalTimeout)
  72. };
  73. }
  74. public override string Execute(string apiCode, IDictionary<string, string> requestParam, IDictionary<string, TopFileItem> fileParam, string session)
  75. {
  76. if (requestParam == null)
  77. {
  78. requestParam = new Dictionary<string, string>();
  79. }
  80. if (fileParam == null)
  81. {
  82. fileParam = new Dictionary<string, TopFileItem>();
  83. }
  84. IDictionary<string,string> systemParam = GetSystemParam();
  85. systemParam.Add(Constants.METHOD,apiCode);
  86. if (!string.IsNullOrEmpty(session))
  87. {
  88. systemParam.Add(Constants.SESSION,session);
  89. }
  90. string sign = TopUtils.SignTopRequest(systemParam,requestParam,appSecret,signMethod);
  91. systemParam.Add(Constants.SIGN,sign);
  92. try
  93. {
  94. if (fileParam == null || fileParam.Count <= 0)
  95. {
  96. return doPost(serverUrl, this.GetHeaderParam(), systemParam, requestParam);
  97. }
  98. return doPostWithFile(serverUrl, this.GetHeaderParam(), systemParam, requestParam, fileParam);
  99. }
  100. catch (ArgumentNullException e)
  101. {
  102. throw new TopException("The request is null.");
  103. }
  104. catch (HttpRequestException e)
  105. {
  106. throw new TopException(
  107. "The request failed due to an underlying issue such as network connectivity, DNS failure, server certificate validation or timeout.");
  108. }
  109. catch (TaskCanceledException e)
  110. {
  111. throw new TopException("The request failed due to timeout.");
  112. }
  113. catch (Exception e)
  114. {
  115. throw new TopException("The request failed :"+e.Message);
  116. }
  117. }
  118. public override string Execute(string apiCode, IDictionary<string, string> requestMap, IDictionary<string, TopFileItem> fileMap)
  119. {
  120. return Execute(apiCode, requestMap, fileMap, null);
  121. }
  122. protected Uri buildUri(string serverUrl, IDictionary<string, string> systemParam)
  123. {
  124. var uriBuilder = new UriBuilder(serverUrl);
  125. var param = HttpUtility.ParseQueryString(string.Empty);
  126. foreach (var item in systemParam)
  127. {
  128. param[item.Key] = item.Value;
  129. }
  130. uriBuilder.Query = param.ToString();
  131. return uriBuilder.Uri;
  132. }
  133. protected string doPost(string serverUrl,IDictionary<string, string> headerParam, IDictionary<string, string> systemParam, IDictionary<string, string> requestParam)
  134. {
  135. var uri = buildUri(serverUrl,systemParam);
  136. var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri)
  137. {
  138. Content = new FormUrlEncodedContent(requestParam)
  139. };
  140. var response = _client.SendAsync(httpRequestMessage);
  141. return response.Result.Content.ReadAsStringAsync().Result;
  142. }
  143. protected string doPostWithFile(string serverUrl, IDictionary<string, string> headerParam,
  144. IDictionary<string, string> systemParam,
  145. IDictionary<string, string> requestParam, IDictionary<string, TopFileItem> fileParam)
  146. {
  147. var uri = buildUri(serverUrl,systemParam);
  148. string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线
  149. byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
  150. byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
  151. var reqStream = new MemoryStream();
  152. if(requestParam != null)
  153. {
  154. // 组装文本请求参数
  155. string textTemplate = "Content-Disposition:form-data;name=\"{0}\"\r\nContent-Type:text/plain\r\n\r\n{1}";
  156. foreach (KeyValuePair<string, string> kv in requestParam)
  157. {
  158. string textEntry = string.Format(textTemplate, kv.Key, kv.Value);
  159. byte[] itemBytes = Encoding.UTF8.GetBytes(textEntry);
  160. reqStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
  161. reqStream.Write(itemBytes, 0, itemBytes.Length);
  162. }
  163. }
  164. // 组装文件请求参数
  165. string fileTemplate = "Content-Disposition:form-data;name=\"{0}\";filename=\"{1}\"\r\nContent-Type:{2}\r\n\r\n";
  166. foreach (KeyValuePair<string, TopFileItem> kv in fileParam)
  167. {
  168. string key = kv.Key;
  169. TopFileItem fileItem = kv.Value;
  170. if (!fileItem.IsValid())
  171. {
  172. throw new ArgumentException("FileItem is invalid");
  173. }
  174. string fileEntry = string.Format(fileTemplate, key, fileItem.GetFileName(), fileItem.GetMimeType());
  175. byte[] itemBytes = Encoding.UTF8.GetBytes(fileEntry);
  176. reqStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
  177. reqStream.Write(itemBytes, 0, itemBytes.Length);
  178. fileItem.Write(reqStream);
  179. }
  180. reqStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
  181. reqStream.Position = 0;
  182. var streamContent = new StreamContent(reqStream,Convert.ToInt32(reqStream.Length));
  183. streamContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data;charset=utf-8;boundary=" + boundary);
  184. var httpRequestMessage = new HttpRequestMessage(HttpMethod.Post, uri)
  185. {
  186. Content = streamContent
  187. };
  188. var response = _client.SendAsync(httpRequestMessage);
  189. return response.Result.Content.ReadAsStringAsync().Result;
  190. }
  191. }