You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

260 lines
9.1 KiB

4 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
3 years ago
  1. using Apewer.Network;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Text;
  5. namespace Apewer.Web
  6. {
  7. /// <summary>请求 API 框架的客户端。</summary>
  8. public class ApiClient
  9. {
  10. private const int DefaultTimeout = 60000;
  11. /// <summary>服务器 URL 根路径。</summary>
  12. public virtual string UrlRoot { get; set; }
  13. /// <summary>使用随机值,并验证响应。</summary>
  14. public virtual bool UseRandom { get; set; }
  15. /// <summary>账号令牌。</summary>
  16. public virtual string Ticket { get; set; }
  17. /// <summary>会话标识。</summary>
  18. public virtual string Session { get; set; }
  19. /// <summary>用户代理。</summary>
  20. public virtual string UserAgent { get; set; }
  21. /// <summary>请求超时,默认值为 60 秒。</summary>
  22. public virtual int Timeout { get; set; } = DefaultTimeout;
  23. void Send(HttpClient client, string random, Action<Json> succeed = null, Action<string> failed = null)
  24. {
  25. client.UserAgent = UserAgent;
  26. var ex = client.Send();
  27. if (ex != null)
  28. {
  29. failed?.Invoke(ex.Message());
  30. return;
  31. }
  32. if (succeed == null && failed == null) return;
  33. var body = client.ResponseData;
  34. if (body == null || body.LongLength < 1L)
  35. {
  36. failed?.Invoke("服务器返回了空数据。");
  37. return;
  38. }
  39. var json = Json.From(body.Text());
  40. if (!json)
  41. {
  42. failed?.Invoke("服务器返回了非 Json 格式的数据。");
  43. return;
  44. }
  45. var status = json["status"];
  46. if (status != "ok")
  47. {
  48. var message = json["message"];
  49. failed?.Invoke(message);
  50. return;
  51. }
  52. var data = json.GetProperty("data");
  53. succeed?.Invoke(data);
  54. }
  55. void Send(HttpClient client, string random, Action<byte[]> succeed = null, Action<string> failed = null)
  56. {
  57. client.UserAgent = UserAgent;
  58. var ex = client.Send();
  59. if (ex != null)
  60. {
  61. failed?.Invoke(ex.Message());
  62. return;
  63. }
  64. if (succeed == null) return;
  65. var body = client.ResponseData;
  66. succeed?.Invoke(body);
  67. }
  68. string Random() => UseRandom ? TextUtility.Random(8) : null;
  69. #region get
  70. /// <summary>发起 GET 请求,获取响应中的 data 属性。</summary>
  71. public void Get(string urlPath, Action<Json> succeed = null, Action<string> failed = null)
  72. {
  73. var random = Random();
  74. var client = Get(urlPath);
  75. Send(client, random, succeed, failed);
  76. }
  77. /// <summary>发起 GET 请求,获取响应的主体。</summary>
  78. public void Get(string urlPath, Action<byte[]> succeed = null, Action<string> failed = null)
  79. {
  80. var random = Random();
  81. var client = Get(urlPath);
  82. Send(client, random, succeed, failed);
  83. }
  84. HttpClient Get(string urlPath)
  85. {
  86. var random = Random();
  87. var client = new HttpClient();
  88. client.Url = MergeUrl(urlPath, random);
  89. client.Method = HttpMethod.GET;
  90. client.Timeout = Timeout;
  91. return client;
  92. }
  93. /// <summary>发起 POST 请求,上传指定数据,获取响应中的 data 属性。</summary>
  94. public void Upload(string urlPath, byte[] bytes, Action<Json> succeed = null, Action<string> failed = null)
  95. {
  96. var random = Random();
  97. var client = Upload(urlPath, random, bytes);
  98. Send(client, random, succeed, failed);
  99. }
  100. /// <summary>发起 POST 请求,上传指定数据,获取响应的主体。</summary>
  101. public void Upload(string urlPath, byte[] bytes, Action<byte[]> succeed = null, Action<string> failed = null)
  102. {
  103. var random = Random();
  104. var client = Upload(urlPath, random, bytes);
  105. Send(client, random, succeed, failed);
  106. }
  107. HttpClient Upload(string urlPath, string random, byte[] bytes)
  108. {
  109. var client = new HttpClient();
  110. client.Url = MergeUrl(urlPath, random);
  111. client.Method = HttpMethod.POST;
  112. client.Timeout = Timeout;
  113. client.RequestContentType = "appliction/octet-stream";
  114. client.RequestData = bytes;
  115. return client;
  116. }
  117. string MergeUrl(string urlPath, string random)
  118. {
  119. var sb = new StringBuilder();
  120. sb.Append(TextUtility.AssureEnds(UrlRoot, "/", true));
  121. var query = null as string;
  122. if (!string.IsNullOrEmpty(urlPath))
  123. {
  124. var offset = urlPath.IndexOf("#");
  125. if (offset > -1) urlPath = urlPath.Substring(0, offset);
  126. offset = urlPath.IndexOf("?");
  127. if (offset < 0)
  128. {
  129. sb.Append(urlPath);
  130. }
  131. else
  132. {
  133. sb.Append(urlPath.Substring(0, offset));
  134. query = urlPath.Substring(offset + 1);
  135. }
  136. }
  137. var session = Session;
  138. var ticket = Ticket;
  139. var ps = ApiUtility.Parameters(query, false);
  140. if (!string.IsNullOrEmpty(random) && !ps.HasKey("random", true)) ps.Add("random", random);
  141. if (!string.IsNullOrEmpty(session) && !ps.HasKey("session", true)) ps.Add("session", session);
  142. if (!string.IsNullOrEmpty(ticket) && !ps.HasKey("ticket", true)) ps.Add("ticket", ticket);
  143. if (ps.Count > 0)
  144. {
  145. var first = true;
  146. foreach (var p in ps)
  147. {
  148. if (first)
  149. {
  150. sb.Append("?");
  151. first = false;
  152. }
  153. else sb.Append("&");
  154. sb.Append(p.Key);
  155. sb.Append("=");
  156. sb.Append(p.Value);
  157. }
  158. }
  159. var url = sb.ToString();
  160. return url;
  161. }
  162. #endregion
  163. #region post
  164. /// <summary>发起 POST 请求,获取响应中的 data 属性。</summary>
  165. public void Post(string urlPath, Json data, Action<Json> succeed = null, Action<string> failed = null)
  166. {
  167. var random = Random();
  168. var client = Post(urlPath, random, null, null, data);
  169. Send(client, random, succeed, failed);
  170. }
  171. /// <summary>发起 POST 请求,获取响应中的 data 属性。</summary>
  172. public void Post(string application, string function, Json data, Action<Json> succeed = null, Action<string> failed = null)
  173. {
  174. var random = Random();
  175. var client = Post(null, random, application, function, data);
  176. Send(client, random, succeed, failed);
  177. }
  178. /// <summary>发起 POST 请求,获取响应的主体。</summary>
  179. public void Post(string urlPath, Json data, Action<byte[]> succeed = null, Action<string> failed = null)
  180. {
  181. var random = Random();
  182. var client = Post(urlPath, random, null, null, data);
  183. Send(client, random, succeed, failed);
  184. }
  185. /// <summary>发起 POST 请求,获取响应的主体。</summary>
  186. public void Post(string application, string function, Json data, Action<byte[]> succeed = null, Action<string> failed = null)
  187. {
  188. var random = Random();
  189. var client = Post(null, random, application, function, data);
  190. Send(client, random, succeed, failed);
  191. }
  192. HttpClient Post(string urlPath, string random, string application, string function, Json data)
  193. {
  194. var json = Json.NewObject();
  195. if (!string.IsNullOrEmpty(application)) json.SetProperty("application", application);
  196. if (!string.IsNullOrEmpty(function)) json.SetProperty("function", function);
  197. if (!string.IsNullOrEmpty(random)) json.SetProperty("random", random);
  198. var session = Session;
  199. if (!string.IsNullOrEmpty(session)) json.SetProperty("session", session);
  200. var ticket = Ticket;
  201. if (!string.IsNullOrEmpty(random)) json.SetProperty("ticket", ticket);
  202. if (data != null) json.SetProperty("data", data);
  203. var url = TextUtility.AssureEnds(UrlRoot, "/", true);
  204. if (!string.IsNullOrEmpty(urlPath)) url += urlPath.StartsWith("/") ? urlPath.Substring(1) : urlPath;
  205. var client = new HttpClient();
  206. client.Url = url;
  207. client.Method = HttpMethod.POST;
  208. client.Timeout = Timeout;
  209. client.RequestContentType = "application/json";
  210. client.RequestData = json.ToString().Bytes();
  211. return client;
  212. }
  213. #endregion
  214. }
  215. }