< Summary

Class:DCL.WebRequestController
Assembly:WebRequest
File(s):/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/WebRequest/WebRequestController.cs
Covered lines:45
Uncovered lines:32
Coverable lines:77
Total lines:481
Line coverage:58.4% (45 of 77)
Covered branches:0
Total branches:0
Covered methods:12
Total methods:22
Method coverage:54.5% (12 of 22)

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity NPath complexity Sequence coverage
WebRequestController(...)0%110100%
Initialize()0%110100%
Create()0%110100%
Initialize(...)0%2100%
GetAsync()0%330100%
PatchAsync()0%12300%
PostAsync()0%330100%
PostAsync()0%12300%
PutAsync()0%12300%
DeleteAsync()0%12300%
GetAssetBundleAsync()0%12300%
GetAssetBundleAsync()0%12300%
GetTextureAsync()0%330100%
GetAudioClipAsync()0%12300%
Get(...)0%110100%
Post(...)0%2100%
GetAssetBundle(...)0%110100%
GetAssetBundle(...)0%2100%
GetTexture(...)0%110100%
GetAudioClip(...)0%110100%
SendWebRequest[T](...)0%5.795068.42%
Dispose()0%220100%

File(s)

/tmp/workspace/unity-renderer/unity-renderer/Assets/Scripts/MainScripts/DCL/Controllers/WebRequest/WebRequestController.cs

#LineLine coverage
 1using Cysharp.Threading.Tasks;
 2using Decentraland.Renderer.KernelServices;
 3using System;
 4using System.Collections.Generic;
 5using System.Threading;
 6using UnityEngine;
 7using UnityEngine.Networking;
 8
 9namespace DCL
 10{
 11    public class WebRequestController : IWebRequestController
 12    {
 13        private const string TIMESTAMP_HEADER = "x-identity-timestamp";
 14        private const string METADATA_HEADER = "x-identity-metadata";
 15
 16        private IWebRequestFactory getWebRequestFactory;
 17        private IWebRequestAssetBundleFactory assetBundleFactory;
 18        private IWebRequestTextureFactory textureFactory;
 19        private IWebRequestAudioFactory audioClipWebRequestFactory;
 20        private IPostWebRequestFactory postWebRequestFactory;
 21        private IPutWebRequestFactory putWebRequestFactory;
 22        private IPatchWebRequestFactory patchWebRequestFactory;
 23        private IDeleteWebRequestFactory deleteWebRequestFactory;
 24        private readonly IRPCSignRequest rpcSignRequest;
 25
 58126        private readonly List<WebRequestAsyncOperation> ongoingWebRequests = new();
 27
 58128        public WebRequestController(
 29            IWebRequestFactory getWebRequestFactory,
 30            IWebRequestAssetBundleFactory assetBundleFactory,
 31            IWebRequestTextureFactory textureFactory,
 32            IWebRequestAudioFactory audioClipWebRequestFactory,
 33            IPostWebRequestFactory postWebRequestFactory,
 34            IPutWebRequestFactory putWebRequestFactory,
 35            IPatchWebRequestFactory patchWebRequestFactory,
 36            IDeleteWebRequestFactory deleteWebRequestFactory,
 37            IRPCSignRequest rpcSignRequest = null
 38        )
 39        {
 58140            this.getWebRequestFactory = getWebRequestFactory;
 58141            this.assetBundleFactory = assetBundleFactory;
 58142            this.textureFactory = textureFactory;
 58143            this.audioClipWebRequestFactory = audioClipWebRequestFactory;
 58144            this.postWebRequestFactory = postWebRequestFactory;
 58145            this.putWebRequestFactory = putWebRequestFactory;
 58146            this.patchWebRequestFactory = patchWebRequestFactory;
 58147            this.deleteWebRequestFactory = deleteWebRequestFactory;
 58148            this.rpcSignRequest = rpcSignRequest;
 58149        }
 50
 56851        public void Initialize() { }
 52
 53        public static WebRequestController Create()
 54        {
 15155            WebRequestController newWebRequestController = new WebRequestController(
 56                new GetWebRequestFactory(),
 57                new WebRequestAssetBundleFactory(),
 58                new WebRequestTextureFactory(),
 59                new WebRequestAudioFactory(),
 60                new PostWebRequestFactory(),
 61                new PutWebRequestFactory(),
 62                new PatchWebRequestFactory(),
 63                new DeleteWebRequestFactory()
 64            );
 65
 15166            return newWebRequestController;
 67        }
 68
 69        public void Initialize(
 70            IWebRequestFactory genericWebRequest,
 71            IWebRequestAssetBundleFactory assetBundleFactoryWebRequest,
 72            IWebRequestTextureFactory textureFactoryWebRequest,
 73            IWebRequestAudioFactory audioClipWebRequest)
 74        {
 075            getWebRequestFactory = genericWebRequest;
 076            assetBundleFactory = assetBundleFactoryWebRequest;
 077            textureFactory = textureFactoryWebRequest;
 078            audioClipWebRequestFactory = audioClipWebRequest;
 079        }
 80
 81        public async UniTask<UnityWebRequest> GetAsync(
 82            string url,
 83            DownloadHandler downloadHandler = null,
 84            Action<UnityWebRequest> onSuccess = null,
 85            Action<UnityWebRequest> onfail = null,
 86            int requestAttemps = 3,
 87            int timeout = 0,
 88            CancellationToken cancellationToken = default,
 89            Dictionary<string, string> headers = null,
 90            bool isSigned = false,
 91            string signUrl = null)
 92        {
 29893            return await SendWebRequest(getWebRequestFactory, url, downloadHandler, onSuccess, onfail, requestAttemps,
 94                timeout, cancellationToken, headers, isSigned, signUrl);
 10095        }
 96
 97        public async UniTask<UnityWebRequest> PatchAsync(
 98            string url,
 99            string patchData,
 100            DownloadHandler downloadHandler = null,
 101            Action<UnityWebRequest> onSuccess = null,
 102            Action<UnityWebRequest> onFail = null,
 103            int requestAttemps = 3,
 104            int timeout = 0,
 105            CancellationToken cancellationToken = default,
 106            Dictionary<string, string> headers = null,
 107            bool isSigned = false)
 108        {
 0109            patchWebRequestFactory.SetBody(patchData);
 0110            return await SendWebRequest(patchWebRequestFactory, url, downloadHandler, onSuccess, onFail, requestAttemps,
 111                timeout, cancellationToken, headers, isSigned);
 0112        }
 113
 114        public async UniTask<UnityWebRequest> PostAsync(
 115            string url,
 116            string postData,
 117            DownloadHandler downloadHandler = null,
 118            Action<UnityWebRequest> onSuccess = null,
 119            Action<UnityWebRequest> onfail = null,
 120            int requestAttemps = 3,
 121            int timeout = 0,
 122            CancellationToken cancellationToken = default,
 123            Dictionary<string, string> headers = null,
 124            bool isSigned = false)
 125        {
 1126            postWebRequestFactory.SetBody(postData);
 3127            return await SendWebRequest(postWebRequestFactory, url, downloadHandler, onSuccess, onfail, requestAttemps,
 128                timeout, cancellationToken, headers, isSigned);
 1129        }
 130
 131        public async UniTask<UnityWebRequest> PostAsync(
 132            string url,
 133            List<IMultipartFormSection> postData,
 134            DownloadHandler downloadHandler = null,
 135            Action<UnityWebRequest> onSuccess = null,
 136            Action<UnityWebRequest> onfail = null,
 137            int requestAttemps = 3,
 138            int timeout = 0,
 139            CancellationToken cancellationToken = default,
 140            Dictionary<string, string> headers = null,
 141            bool isSigned = false)
 142        {
 0143            postWebRequestFactory.SetBody(postData);
 0144            return await SendWebRequest(postWebRequestFactory, url, downloadHandler, onSuccess, onfail, requestAttemps,
 145                timeout, cancellationToken, headers, isSigned);
 0146        }
 147
 148        public async UniTask<UnityWebRequest> PutAsync(
 149            string url,
 150            string putData,
 151            DownloadHandler downloadHandler = null,
 152            Action<UnityWebRequest> onSuccess = null,
 153            Action<UnityWebRequest> onfail = null,
 154            int requestAttemps = 3,
 155            int timeout = 0,
 156            CancellationToken cancellationToken = default,
 157            Dictionary<string, string> headers = null,
 158            bool isSigned = false)
 159        {
 0160            putWebRequestFactory.SetBody(putData);
 0161            return await SendWebRequest(putWebRequestFactory, url, downloadHandler, onSuccess, onfail, requestAttemps,
 162                timeout, cancellationToken, headers, isSigned);
 0163        }
 164
 165        public async UniTask<UnityWebRequest> DeleteAsync(
 166            string url,
 167            DownloadHandler downloadHandler = null,
 168            Action<UnityWebRequest> onSuccess = null,
 169            Action<UnityWebRequest> onFail = null,
 170            int requestAttemps = 3,
 171            int timeout = 0,
 172            CancellationToken cancellationToken = default,
 173            Dictionary<string, string> headers = null,
 174            bool isSigned = false)
 175        {
 0176            return await SendWebRequest(deleteWebRequestFactory, url, downloadHandler, onSuccess, onFail, requestAttemps
 177                timeout, cancellationToken, headers, isSigned);
 0178        }
 179
 180        public async UniTask<UnityWebRequest> GetAssetBundleAsync(
 181            string url,
 182            Action<UnityWebRequest> onSuccess = null,
 183            Action<UnityWebRequest> onfail = null,
 184            int requestAttemps = 3,
 185            int timeout = 0,
 186            CancellationToken cancellationToken = default)
 187        {
 0188            return await SendWebRequest(assetBundleFactory, url, null, onSuccess, onfail, requestAttemps,
 189                timeout, cancellationToken);
 0190        }
 191
 192        public async UniTask<UnityWebRequest> GetAssetBundleAsync(
 193            string url,
 194            Hash128 hash,
 195            Action<UnityWebRequest> onSuccess = null,
 196            Action<UnityWebRequest> onfail = null,
 197            int requestAttemps = 3,
 198            int timeout = 0,
 199            CancellationToken cancellationToken = default)
 200        {
 0201            assetBundleFactory.SetHash(hash);
 0202            return await SendWebRequest(assetBundleFactory, url, null, onSuccess, onfail, requestAttemps,
 203                timeout, cancellationToken);
 0204        }
 205
 206        public async UniTask<UnityWebRequest> GetTextureAsync(
 207            string url,
 208            Action<UnityWebRequest> onSuccess = null,
 209            Action<UnityWebRequest> onfail = null,
 210            int requestAttemps = 3,
 211            int timeout = 0,
 212            bool isReadable = true,
 213            CancellationToken cancellationToken = default,
 214            Dictionary<string, string> headers = null)
 215        {
 1100216            textureFactory.isReadable = isReadable;
 3300217            return await SendWebRequest(textureFactory, url, null, onSuccess, onfail, requestAttemps, timeout, cancellat
 151218        }
 219
 220        public async UniTask<UnityWebRequest> GetAudioClipAsync(
 221            string url,
 222            AudioType audioType,
 223            Action<UnityWebRequest> onSuccess = null,
 224            Action<UnityWebRequest> onfail = null,
 225            int requestAttemps = 3,
 226            int timeout = 0,
 227            CancellationToken cancellationToken = default)
 228        {
 0229            audioClipWebRequestFactory.SetAudioType(audioType);
 0230            return await SendWebRequest(audioClipWebRequestFactory, url, null, onSuccess, onfail, requestAttemps,
 231                timeout, cancellationToken);
 0232        }
 233
 234
 235        private async UniTask<UnityWebRequest> SendWebRequest<T>(
 236            T requestFactory,
 237            string url,
 238            DownloadHandler downloadHandler,
 239            Action<UnityWebRequest> onSuccess,
 240            Action<UnityWebRequest> onFail,
 241            int requestAttemps,
 242            int timeout,
 243            CancellationToken cancellationToken,
 244            Dictionary<string, string> headers = null,
 245            bool isSigned = false,
 246            string signUrl = null) where T : IWebRequestFactory
 247        {
 248            requestAttemps = Mathf.Max(1, requestAttemps);
 249
 250            for (int i = requestAttemps - 1; i >= 0; i--)
 251            {
 252                UnityWebRequest request = requestFactory.CreateWebRequest(url);
 253                request.timeout = timeout;
 254
 255                if (isSigned)
 256                {
 257                    if (!Enum.TryParse(request.method, true, out RequestMethod method))
 258                        method = RequestMethod.Get;
 259
 260                    int index = url.IndexOf("?", StringComparison.Ordinal);
 261                    if (index >= 0)
 262                        url = url.Substring(0, index);
 263
 264                    SignBodyResponse signedFetchResponse = await rpcSignRequest.RequestSignedRequest(method, signUrl ?? 
 265
 266                    await UniTask.SwitchToMainThread();
 267                    for (var j = 0; j < signedFetchResponse.AuthChain.Count; j++)
 268                    {
 269                        request.SetRequestHeader($"x-identity-auth-chain-{j}", signedFetchResponse.AuthChain[j]);
 270                    }
 271                    request.SetRequestHeader(TIMESTAMP_HEADER, signedFetchResponse.Timestamp.ToString());
 272                    request.SetRequestHeader(METADATA_HEADER, signedFetchResponse.Metadata);
 273                }
 274
 275                if (headers != null)
 276                {
 277                    foreach (var item in headers)
 278                        request.SetRequestHeader(item.Key, item.Value);
 279                }
 280
 281                if (downloadHandler != null)
 282                    request.downloadHandler = downloadHandler;
 283
 284                UnityWebRequestAsyncOperation asyncOp = request.SendWebRequest();
 285                await asyncOp.WithCancellation(cancellationToken);
 286
 287                if (request.WebRequestSucceded())
 288                {
 289                    onSuccess?.Invoke(asyncOp.webRequest);
 290                    return asyncOp.webRequest;
 291                }
 292                else if (!request.WebRequestAborted() && request.WebRequestServerError())
 293                {
 294                    if (requestAttemps > 0)
 295                        continue;
 296                    else
 297                    {
 298                        onFail?.Invoke(asyncOp.webRequest);
 299                        return asyncOp.webRequest;
 300                    }
 301                }
 302                else
 303                {
 304                    onFail?.Invoke(asyncOp.webRequest);
 305                    return asyncOp.webRequest;
 306                }
 307            }
 308
 309            throw new Exception("WebRequestController SendWebRequest: Unexpected error");
 310        }
 311
 312        [Obsolete]
 313        public IWebRequestAsyncOperation Get(
 314            string url,
 315            DownloadHandler downloadHandler = null,
 316            Action<IWebRequestAsyncOperation> OnSuccess = null,
 317            Action<IWebRequestAsyncOperation> OnFail = null,
 318            int requestAttemps = 3,
 319            int timeout = 0,
 320            bool disposeOnCompleted = true,
 321            Dictionary<string, string> headers = null)
 322        {
 16323            return SendWebRequest(getWebRequestFactory, url, downloadHandler, OnSuccess, OnFail, requestAttemps, timeout
 324        }
 325
 326        [Obsolete]
 327        public IWebRequestAsyncOperation Post(
 328            string url,
 329            string postData,
 330            DownloadHandler downloadHandler = null,
 331            Action<IWebRequestAsyncOperation> OnSuccess = null,
 332            Action<IWebRequestAsyncOperation> OnFail = null,
 333            int requestAttemps = 3,
 334            int timeout = 0,
 335            bool disposeOnCompleted = true,
 336            Dictionary<string, string> headers = null)
 337        {
 0338            postWebRequestFactory.SetBody(postData);
 0339            return SendWebRequest(postWebRequestFactory, url, downloadHandler, OnSuccess, OnFail, requestAttemps, timeou
 340        }
 341
 342        [Obsolete]
 343        public IWebRequestAsyncOperation GetAssetBundle(
 344            string url,
 345            Action<IWebRequestAsyncOperation> OnSuccess = null,
 346            Action<IWebRequestAsyncOperation> OnFail = null,
 347            int requestAttemps = 3,
 348            int timeout = 0,
 349            bool disposeOnCompleted = true)
 350        {
 29351            return SendWebRequest(assetBundleFactory, url, null, OnSuccess, OnFail, requestAttemps, timeout, disposeOnCo
 352        }
 353
 354        [Obsolete]
 355        public IWebRequestAsyncOperation GetAssetBundle(
 356            string url,
 357            Hash128 hash,
 358            Action<IWebRequestAsyncOperation> OnSuccess = null,
 359            Action<IWebRequestAsyncOperation> OnFail = null,
 360            int requestAttemps = 3,
 361            int timeout = 0,
 362            bool disposeOnCompleted = true)
 363        {
 0364            assetBundleFactory.SetHash(hash);
 0365            return SendWebRequest(assetBundleFactory, url, null, OnSuccess, OnFail, requestAttemps, timeout, disposeOnCo
 366        }
 367
 368        [Obsolete]
 369        public IWebRequestAsyncOperation GetTexture(
 370            string url,
 371            Action<IWebRequestAsyncOperation> OnSuccess = null,
 372            Action<IWebRequestAsyncOperation> OnFail = null,
 373            int requestAttemps = 3,
 374            int timeout = 0,
 375            bool disposeOnCompleted = true,
 376            bool isReadable = true,
 377            Dictionary<string, string> headers = null)
 378        {
 118379            textureFactory.isReadable = isReadable;
 118380            return SendWebRequest(textureFactory, url, null, OnSuccess, OnFail, requestAttemps, timeout, disposeOnComple
 381        }
 382
 383        [Obsolete]
 384        public IWebRequestAsyncOperation GetAudioClip(
 385            string url,
 386            AudioType audioType,
 387            Action<IWebRequestAsyncOperation> OnSuccess = null,
 388            Action<IWebRequestAsyncOperation> OnFail = null,
 389            int requestAttemps = 3,
 390            int timeout = 0,
 391            bool disposeOnCompleted = true)
 392        {
 39393            audioClipWebRequestFactory.SetAudioType(audioType);
 39394            return SendWebRequest(audioClipWebRequestFactory, url, null, OnSuccess, OnFail, requestAttemps, timeout, dis
 395        }
 396
 397        private WebRequestAsyncOperation SendWebRequest<T>(
 398            T requestFactory,
 399            string url,
 400            DownloadHandler downloadHandler,
 401            Action<IWebRequestAsyncOperation> OnSuccess,
 402            Action<IWebRequestAsyncOperation> OnFail,
 403            int requestAttemps,
 404            int timeout,
 405            bool disposeOnCompleted,
 406            Dictionary<string, string> headers = null,
 407            WebRequestAsyncOperation asyncOp = null
 408        ) where T : IWebRequestFactory
 409        {
 202410            int remainingAttemps = Mathf.Clamp(requestAttemps, 1, requestAttemps);
 411
 202412            UnityWebRequest request = requestFactory.CreateWebRequest(url);
 413
 202414            request.timeout = timeout;
 415
 202416            if (headers != null)
 417            {
 0418                foreach (var item in headers)
 0419                { request.SetRequestHeader(item.Key, item.Value); }
 420            }
 421
 202422            if (downloadHandler != null)
 0423                request.downloadHandler = downloadHandler;
 424
 202425            WebRequestAsyncOperation resultOp = asyncOp;
 426
 202427            if (resultOp == null)
 202428                resultOp = new WebRequestAsyncOperation(request);
 429            else
 0430                resultOp.SetNewWebRequest(request);
 431
 202432            resultOp.disposeOnCompleted = disposeOnCompleted;
 202433            ongoingWebRequests.Add(resultOp);
 434
 202435            UnityWebRequestAsyncOperation requestOp = resultOp.SendWebRequest();
 436
 202437            requestOp.completed += (asyncOp) =>
 438            {
 439                if (!resultOp.isDisposed)
 440                {
 441                    if (resultOp.webRequest.WebRequestSucceded())
 442                    {
 443                        OnSuccess?.Invoke(resultOp);
 444                        resultOp.SetAsCompleted(true);
 445                    }
 446                    else if (!resultOp.webRequest.WebRequestAborted() && resultOp.webRequest.WebRequestServerError())
 447                    {
 448                        remainingAttemps--;
 449
 450                        if (remainingAttemps > 0)
 451                        {
 452                            resultOp.Dispose();
 453                            resultOp = SendWebRequest(requestFactory, url, downloadHandler, OnSuccess, OnFail, remaining
 454                        }
 455                        else
 456                        {
 457                            OnFail?.Invoke(resultOp);
 458                            resultOp.SetAsCompleted(false);
 459                        }
 460                    }
 461                    else
 462                    {
 463                        OnFail?.Invoke(resultOp);
 464                        resultOp.SetAsCompleted(false);
 465                    }
 466                }
 467
 468                ongoingWebRequests.Remove(resultOp);
 469            };
 470
 202471            return resultOp;
 472        }
 473
 474
 475        public void Dispose()
 476        {
 1206477            foreach (var webRequest in ongoingWebRequests)
 15478                webRequest.Dispose();
 588479        }
 480    }
 481}

Methods/Properties

WebRequestController(DCL.IWebRequestFactory, DCL.IWebRequestAssetBundleFactory, DCL.IWebRequestTextureFactory, DCL.IWebRequestAudioFactory, DCL.IPostWebRequestFactory, DCL.IPutWebRequestFactory, DCL.IPatchWebRequestFactory, DCL.IDeleteWebRequestFactory, IRPCSignRequest)
Initialize()
Create()
Initialize(DCL.IWebRequestFactory, DCL.IWebRequestAssetBundleFactory, DCL.IWebRequestTextureFactory, DCL.IWebRequestAudioFactory)
GetAsync()
PatchAsync()
PostAsync()
PostAsync()
PutAsync()
DeleteAsync()
GetAssetBundleAsync()
GetAssetBundleAsync()
GetTextureAsync()
GetAudioClipAsync()
Get(System.String, UnityEngine.Networking.DownloadHandler, System.Action[IWebRequestAsyncOperation], System.Action[IWebRequestAsyncOperation], System.Int32, System.Int32, System.Boolean, System.Collections.Generic.Dictionary[String,String])
Post(System.String, System.String, UnityEngine.Networking.DownloadHandler, System.Action[IWebRequestAsyncOperation], System.Action[IWebRequestAsyncOperation], System.Int32, System.Int32, System.Boolean, System.Collections.Generic.Dictionary[String,String])
GetAssetBundle(System.String, System.Action[IWebRequestAsyncOperation], System.Action[IWebRequestAsyncOperation], System.Int32, System.Int32, System.Boolean)
GetAssetBundle(System.String, UnityEngine.Hash128, System.Action[IWebRequestAsyncOperation], System.Action[IWebRequestAsyncOperation], System.Int32, System.Int32, System.Boolean)
GetTexture(System.String, System.Action[IWebRequestAsyncOperation], System.Action[IWebRequestAsyncOperation], System.Int32, System.Int32, System.Boolean, System.Boolean, System.Collections.Generic.Dictionary[String,String])
GetAudioClip(System.String, UnityEngine.AudioType, System.Action[IWebRequestAsyncOperation], System.Action[IWebRequestAsyncOperation], System.Int32, System.Int32, System.Boolean)
SendWebRequest[T](T, System.String, UnityEngine.Networking.DownloadHandler, System.Action[IWebRequestAsyncOperation], System.Action[IWebRequestAsyncOperation], System.Int32, System.Int32, System.Boolean, System.Collections.Generic.Dictionary[String,String], DCL.WebRequestAsyncOperation)
Dispose()