|
|
using Apewer.Network; using System; using System.Collections.Generic; using System.Text;
namespace Apewer.Web {
/// <summary>请求 API 框架的客户端。</summary>
public class ApiClient {
private const int DefaultTimeout = 60000;
/// <summary>服务器 URL 根路径。</summary>
public virtual string UrlRoot { get; set; }
/// <summary>使用随机值,并验证响应。</summary>
public virtual bool UseRandom { get; set; }
/// <summary>账号令牌。</summary>
public virtual string Ticket { get; set; }
/// <summary>会话标识。</summary>
public virtual string Session { get; set; }
/// <summary>用户代理。</summary>
public virtual string UserAgent { get; set; }
/// <summary>请求超时,默认值为 60 秒。</summary>
public virtual int Timeout { get; set; } = DefaultTimeout;
void Send(HttpClient client, string random, Action<Json> succeed = null, Action<string> failed = null) { client.UserAgent = UserAgent; var ex = client.Send(); if (ex != null) { failed?.Invoke(ex.Message()); return; }
if (succeed == null && failed == null) return;
var body = client.ResponseData; if (body == null || body.LongLength < 1L) { failed?.Invoke("服务器返回了空数据。"); return; }
var json = Json.From(body.Text()); if (!json) { failed?.Invoke("服务器返回了非 Json 格式的数据。"); return; }
var status = json["status"]; if (status != "ok") { var message = json["message"]; failed?.Invoke(message); return; }
var data = json.GetProperty("data"); succeed?.Invoke(data); }
void Send(HttpClient client, string random, Action<byte[]> succeed = null, Action<string> failed = null) { client.UserAgent = UserAgent; var ex = client.Send(); if (ex != null) { failed?.Invoke(ex.Message()); return; }
if (succeed == null) return;
var body = client.ResponseData; succeed?.Invoke(body); }
string Random() => UseRandom ? TextUtility.Random(8) : null;
#region get
/// <summary>发起 GET 请求,获取响应中的 data 属性。</summary>
public void Get(string urlPath, Action<Json> succeed = null, Action<string> failed = null) { var random = Random(); var client = Get(urlPath); Send(client, random, succeed, failed); }
/// <summary>发起 GET 请求,获取响应的主体。</summary>
public void Get(string urlPath, Action<byte[]> succeed = null, Action<string> failed = null) { var random = Random(); var client = Get(urlPath); Send(client, random, succeed, failed); }
HttpClient Get(string urlPath) { var random = Random(); var client = new HttpClient(); client.Url = MergeUrl(urlPath, random); client.Method = HttpMethod.GET; client.Timeout = Timeout; return client; }
/// <summary>发起 POST 请求,上传指定数据,获取响应中的 data 属性。</summary>
public void Upload(string urlPath, byte[] bytes, Action<Json> succeed = null, Action<string> failed = null) { var random = Random(); var client = Upload(urlPath, random, bytes); Send(client, random, succeed, failed); }
/// <summary>发起 POST 请求,上传指定数据,获取响应的主体。</summary>
public void Upload(string urlPath, byte[] bytes, Action<byte[]> succeed = null, Action<string> failed = null) { var random = Random(); var client = Upload(urlPath, random, bytes); Send(client, random, succeed, failed); }
HttpClient Upload(string urlPath, string random, byte[] bytes) { var client = new HttpClient(); client.Url = MergeUrl(urlPath, random); client.Method = HttpMethod.POST; client.Timeout = Timeout; client.RequestContentType = "appliction/octet-stream"; client.RequestData = bytes; return client; }
string MergeUrl(string urlPath, string random) { var sb = new StringBuilder(); sb.Append(TextUtility.AssureEnds(UrlRoot, "/", true));
var query = null as string; if (!string.IsNullOrEmpty(urlPath)) { var offset = urlPath.IndexOf("#"); if (offset > -1) urlPath = urlPath.Substring(0, offset);
offset = urlPath.IndexOf("?"); if (offset < 0) { sb.Append(urlPath); } else { sb.Append(urlPath.Substring(0, offset)); query = urlPath.Substring(offset + 1); } }
var session = Session; var ticket = Ticket; var ps = ApiUtility.Parameters(query, false); if (!string.IsNullOrEmpty(random) && !ps.HasKey("random", true)) ps.Add("random", random); if (!string.IsNullOrEmpty(session) && !ps.HasKey("session", true)) ps.Add("session", session); if (!string.IsNullOrEmpty(ticket) && !ps.HasKey("ticket", true)) ps.Add("ticket", ticket); if (ps.Count > 0) { var first = true; foreach (var p in ps) { if (first) { sb.Append("?"); first = false; } else sb.Append("&"); sb.Append(p.Key); sb.Append("="); sb.Append(p.Value); } } var url = sb.ToString(); return url; }
#endregion
#region post
/// <summary>发起 POST 请求,获取响应中的 data 属性。</summary>
public void Post(string urlPath, Json data, Action<Json> succeed = null, Action<string> failed = null) { var random = Random(); var client = Post(urlPath, random, null, null, data); Send(client, random, succeed, failed); }
/// <summary>发起 POST 请求,获取响应中的 data 属性。</summary>
public void Post(string application, string function, Json data, Action<Json> succeed = null, Action<string> failed = null) { var random = Random(); var client = Post(null, random, application, function, data); Send(client, random, succeed, failed); }
/// <summary>发起 POST 请求,获取响应的主体。</summary>
public void Post(string urlPath, Json data, Action<byte[]> succeed = null, Action<string> failed = null) { var random = Random(); var client = Post(urlPath, random, null, null, data); Send(client, random, succeed, failed); }
/// <summary>发起 POST 请求,获取响应的主体。</summary>
public void Post(string application, string function, Json data, Action<byte[]> succeed = null, Action<string> failed = null) { var random = Random(); var client = Post(null, random, application, function, data); Send(client, random, succeed, failed); }
HttpClient Post(string urlPath, string random, string application, string function, Json data) { var json = Json.NewObject(); if (!string.IsNullOrEmpty(application)) json.SetProperty("application", application); if (!string.IsNullOrEmpty(function)) json.SetProperty("function", function); if (!string.IsNullOrEmpty(random)) json.SetProperty("random", random);
var session = Session; if (!string.IsNullOrEmpty(session)) json.SetProperty("session", session);
var ticket = Ticket; if (!string.IsNullOrEmpty(random)) json.SetProperty("ticket", ticket);
if (data != null) json.SetProperty("data", data);
var url = TextUtility.AssureEnds(UrlRoot, "/", true); if (!string.IsNullOrEmpty(urlPath)) url += urlPath.StartsWith("/") ? urlPath.Substring(1) : urlPath;
var client = new HttpClient(); client.Url = url; client.Method = HttpMethod.POST; client.Timeout = Timeout; client.RequestContentType = "application/json"; client.RequestData = json.ToString().Bytes(); return client; }
#endregion
}
}
|