简化api调用流程,非常奈斯。
RestWebClient.cs
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.Networking;
namespace MYTOOL.RestClient
{
/// <summary>
/// UnityWebRequest封装类
/// </summary>
public class RestWebClient
{
private readonly MonoBehaviour executer;
public RestWebClient(MonoBehaviour executer)
{
if (executer == null) throw new ArgumentNullException();
this.executer = executer;
}
#region >> GET
public Coroutine Get(string url, Request req)
{
if (req == null) throw new ArgumentNullException();
return executer.StartCoroutine(InnerGet(url, req));
}
#endregion
#region >> PUT
public Coroutine Put(string url, Request req)
{
if (req == null) throw new ArgumentNullException();
return executer.StartCoroutine(InnerPut(url, req));
}
#endregion
#region >> POST
public Coroutine Post(string url, Request req)
{
if (req == null) throw new ArgumentNullException();
return executer.StartCoroutine(InnerPost(url, req));
}
public Coroutine PostForm(string url, WWWForm formData, Request req)
{
if (req == null) throw new ArgumentNullException();
return executer.StartCoroutine(InnerPostForm(url, formData, req));
}
#endregion
#region >> DELETE
public Coroutine Delete(string url, Request req)
{
if (req == null) throw new ArgumentNullException();
return executer.StartCoroutine(InnerDelete(url, req));
}
#endregion
private IEnumerator InnerGet(string url, Request req)
{
req.OnBegin?.Invoke();
ushort retryCount = req.RetryCount;
do
{
using UnityWebRequest webRequest = UnityWebRequest.Get(url);
InitUnityWebRequest(webRequest, req);
yield return webRequest.SendWebRequest();
bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
if (isSuccess || retryCount == 0)
{
if (DebugMode) LogInfo("GET", webRequest.responseCode, isSuccess, webRequest.url);
req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
yield break;
}
if (req.RetryInterval > 0)
{
yield return new WaitForSeconds(req.RetryInterval);
}
} while (retryCount-- > 0);
}
private IEnumerator InnerPut(string url, Request req)
{
req.OnBegin?.Invoke();
ushort retryCount = req.RetryCount;
do
{
using UnityWebRequest webRequest = UnityWebRequest.Put(url, req.BodyData);
InitUnityWebRequest(webRequest, req);
yield return webRequest.SendWebRequest();
bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
if (isSuccess || retryCount == 0)
{
if (DebugMode) LogInfo("PUT", webRequest.responseCode, isSuccess, webRequest.url);
req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
yield break;
}
if (req.RetryInterval > 0)
{
yield return new WaitForSeconds(req.RetryInterval);
}
} while (retryCount-- > 0);
}
private IEnumerator InnerPost(string url, Request req)
{
req.OnBegin?.Invoke();
ushort retryCount = req.RetryCount;
do
{
using UnityWebRequest webRequest = UnityWebRequest.Post(url, req.BodyData);
InitUnityWebRequest(webRequest, req);
yield return webRequest.SendWebRequest();
bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
if (isSuccess || retryCount == 0)
{
if (DebugMode) LogInfo("POST", webRequest.responseCode, isSuccess, webRequest.url);
req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
yield break;
}
if (req.RetryInterval > 0)
{
yield return new WaitForSeconds(req.RetryInterval);
}
} while (retryCount-- > 0);
}
private IEnumerator InnerPostForm(string url, WWWForm formData, Request req)
{
req.OnBegin?.Invoke();
ushort retryCount = req.RetryCount;
do
{
using UnityWebRequest webRequest = UnityWebRequest.Post(url, formData);
InitUnityWebRequest(webRequest, req);
yield return webRequest.SendWebRequest();
bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
if (isSuccess || retryCount == 0)
{
if (DebugMode) LogInfo("POST", webRequest.responseCode, isSuccess, webRequest.url);
req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
yield break;
}
if (req.RetryInterval > 0)
{
yield return new WaitForSeconds(req.RetryInterval);
}
} while (retryCount-- > 0);
}
private IEnumerator InnerDelete(string url, Request req)
{
req.OnBegin?.Invoke();
ushort retryCount = req.RetryCount;
do
{
using UnityWebRequest webRequest = UnityWebRequest.Delete(url);
webRequest.downloadHandler = new DownloadHandlerBuffer();
InitUnityWebRequest(webRequest, req);
yield return webRequest.SendWebRequest();
bool isSuccess = webRequest.result == UnityWebRequest.Result.Success;
if (isSuccess || retryCount == 0)
{
if (DebugMode) LogInfo("DELETE", webRequest.responseCode, isSuccess, webRequest.url);
req.Invoke(isSuccess, webRequest.responseCode, webRequest.downloadHandler.data, webRequest.error);
yield break;
}
if (req.RetryInterval > 0)
{
yield return new WaitForSeconds(req.RetryInterval);
}
} while (retryCount-- > 0);
}
private void InitUnityWebRequest(UnityWebRequest webRequest, Request req)
{
webRequest.timeout = req.Timeout;
if (webRequest.uploadHandler != null && string.IsNullOrEmpty(req.ContentType) == false)
{
webRequest.uploadHandler.contentType = req.ContentType;
}
var queryString = req.GetQueryString();
if (string.IsNullOrEmpty(queryString) == false)
{
if (webRequest.url.EndsWith('?'))
{
webRequest.url += queryString;
}
else
{
webRequest.url += $"?{queryString}";
}
}
var headers = req.GetHeaders();
foreach (var header in headers)
{
webRequest.SetRequestHeader(header.Key, header.Value);
}
}
public static bool DebugMode = true;
private static void LogInfo(string method, long code, bool success, string info)
{
string str = success ? $"<color=green>{info}</color>" : $"<color=red>{info}</color>";
Debug.Log($"[{method}] [{code}] => {str}");
}
}
}
Request.cs
using System;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace MYTOOL.RestClient
{
public class Request
{
public const string APPLICATION_JSON = "application/json";
/// <summary>
/// 超时时间
/// </summary>
public int Timeout { get; private set; }
/// <summary>
/// 重试次数
/// </summary>
public ushort RetryCount { get; private set; }
/// <summary>
/// 重试间隔(秒)
/// </summary>
public float RetryInterval { get; private set; }
/// <summary>
/// 内容
/// </summary>
public string BodyData { get; private set; }
/// <summary>
/// 内容类型
/// </summary>
public string ContentType { get; private set; }
/// <summary>
/// 请求是否完成
/// </summary>
public bool IsDone { get; private set; }
/// <summary>
/// 请求开始前的回调
/// </summary>
public Action OnBegin;
/// <summary>
/// 请求完成后的回调
/// </summary>
private readonly Action<Response> OnComplete;
private readonly Dictionary<string, string> Headers;
private readonly Dictionary<string, List<string>> Query;
public Request(Action<Response> onComplete, int timeout = 10)
{
OnComplete = onComplete;
Timeout = timeout;
Headers = new Dictionary<string, string>();
Query = new Dictionary<string, List<string>>();
}
public Request(Action<Response> onComplete, string bodyData, int timeout = 10) : this(onComplete, timeout)
{
BodyData = bodyData;
}
public Request Reset()
{
IsDone = false;
return this;
}
internal void Invoke(bool succeed, long statusCode, byte[] data, string error)
{
IsDone = true;
OnComplete?.Invoke(new Response(succeed, statusCode, data, error));
}
public Request AddQuery(string key, string value)
{
if (Query.ContainsKey(key) == false)
{
Query[key] = new List<string>();
}
Query[key].Add(value);
return this;
}
public bool RemoveQuery(string key)
{
return Query.Remove(key);
}
public Request SetRequestHeader(string key, string value)
{
Headers[key] = value;
return this;
}
public Dictionary<string, string> GetHeaders()
{
return new Dictionary<string, string>(Headers);
}
public string GetQueryString()
{
StringBuilder sb = new StringBuilder();
foreach (var kv in Query)
{
if (sb.Length > 0 && kv.Value.Count > 0) sb.Append('&');
// 将每个键值对转换为字符串并连接起来
var values = string.Join('&', kv.Value.Select(value => $"{kv.Key}={value}"));
sb.Append(values);
}
return sb.ToString();
}
/// <summary>
/// 设置超时时间
/// </summary>
/// <param name="timeout"></param>
/// <returns></returns>
public Request SetTimeout(int timeout)
{
Timeout = timeout;
return this;
}
/// <summary>
/// 设置重试参数
/// </summary>
/// <param name="retryCount">重试次数</param>
/// <param name="sec">重试间隔(秒)</param>
/// <returns></returns>
public Request SetRetryOption(ushort retryCount, float retryInterval)
{
RetryCount = retryCount;
RetryInterval = retryInterval;
return this;
}
/// <summary>
/// 设置Body内容
/// </summary>
/// <param name="bodyData"></param>
/// <returns></returns>
public Request SetBodyData(string bodyData)
{
BodyData = bodyData;
return this;
}
/// <summary>
/// 设置Body内容,并指定内容类型
/// </summary>
/// <param name="bodyData"></param>
/// <param name="contentType">如:application/json</param>
/// <returns></returns>
public Request SetBodyData(string bodyData, string contentType)
{
BodyData = bodyData;
ContentType = contentType;
return this;
}
/// <summary>
/// 设置内容类型
/// </summary>
/// <param name="contentType">如:application/json</param>
/// <returns></returns>
public Request SetContentType(string contentType)
{
ContentType = contentType;
return this;
}
}
}
Response.cs
using System.Text;
namespace MYTOOL.RestClient
{
public class Response
{
public bool Succeed { get; }
public long StatusCode { get; }
public byte[] Data { get; }
public string Error { get; }
public bool HasError => string.IsNullOrEmpty(Error) == false;
public Response(bool succeed, long statusCode, byte[] data, string error)
{
Succeed = succeed;
StatusCode = statusCode;
Data = data;
Error = error;
}
public string GetResponseData(Encoding encoding = null)
{
if (Data == null) return "";
encoding ??= Encoding.UTF8;
return encoding.GetString(Data);
}
}
}
使用例子
using MYTOOL.RestClient;
using UnityEngine;
public class NewBehaviourScript : MonoBehaviour
{
private RestWebClient client;
private void Awake()
{
//初始化
client = new RestWebClient(this);
}
private void Start()
{
//设置请求完成后回调 与 超时时间
Request req = new Request(OnGetBaidu, 30);
//设置重试次数 与 重试间隔
req.SetRetryOption(3, 0.2f);
client.Get("https://www.baidu.com/", req);
}
void OnGetBaidu(Response resp)
{
if (resp.Succeed)
{
if (resp.StatusCode == 200 || resp.StatusCode == 204)
{
Debug.Log($"请求成功,{resp.GetResponseData()}");
}
}
else
{
Debug.Log($"请求失败,{resp.Error}");
}
}
}