Unity UnityWebRequest封装类

简化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}");
        }
    }
}

在这里插入图片描述

  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值