diff --git a/Runtime/Rest.cs b/Runtime/Rest.cs index f6a7954..b184db4 100644 --- a/Runtime/Rest.cs +++ b/Runtime/Rest.cs @@ -429,34 +429,22 @@ public static string GetBearerOAuthToken(string authToken) #region Download Cache - private const string DOWNLOAD_CACHE = "download_cache"; + private const string download_cache = nameof(download_cache); private static IDownloadCache cache; private static IDownloadCache Cache - { - get + => cache ??= Application.platform switch { - if (cache != null) - { - return cache; - } - - cache = Application.platform switch - { - RuntimePlatform.WebGLPlayer => new NoOpDownloadCache(), - _ => new DiskDownloadCache() - }; - - return cache; - } - } + RuntimePlatform.WebGLPlayer => new NoOpDownloadCache(), + _ => new DiskDownloadCache() + }; /// /// The download cache directory.
///
public static string DownloadCacheDirectory - => Path.Combine(Application.temporaryCachePath, DOWNLOAD_CACHE); + => Path.Combine(Application.temporaryCachePath, download_cache); /// /// Creates the if it doesn't exist. @@ -510,19 +498,31 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) #endregion Download Cache + [Obsolete("use new overload with debug support")] + public static async Task DownloadTextureAsync( + string url, + string fileName = null, + RestParameters parameters = null, + CancellationToken cancellationToken = default) + { + return await DownloadTextureAsync(url, fileName, parameters, false, cancellationToken); + } + /// /// Download a from the provided . /// /// The url to download the from. /// Optional, file name to download (including extension). /// Optional, . + /// Optional, debug http request. /// Optional, . /// A new instance. public static async Task DownloadTextureAsync( - string url, - string fileName = null, - RestParameters parameters = null, - CancellationToken cancellationToken = default) + string url, + string fileName = null, + RestParameters parameters = null, + bool debug = false, + CancellationToken cancellationToken = default) { await Awaiters.UnityMainThread; @@ -549,28 +549,22 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) url = cachePath; } - using var webRequest = UnityWebRequestTexture.GetTexture(url); - parameters ??= new RestParameters(); - parameters.DisposeDownloadHandler = false; - var response = await webRequest.SendAsync(parameters, cancellationToken); - - if (!response.Successful) - { - throw new RestException(response, $"Failed to download texture from \"{url}\"!"); - } - Texture2D texture; - var downloadHandler = (DownloadHandlerTexture)webRequest.downloadHandler; + parameters ??= new RestParameters(); + parameters.DisposeDownloadHandler = true; + using var webRequest = UnityWebRequestTexture.GetTexture(url); try { + var response = await webRequest.SendAsync(parameters, cancellationToken); + response.Validate(debug); + if (!isCached) { - await Cache.WriteCacheItemAsync(downloadHandler.data, cachePath, cancellationToken); + await Cache.WriteCacheItemAsync(webRequest.downloadHandler.data, cachePath, cancellationToken).ConfigureAwait(true); } - await Awaiters.UnityMainThread; - texture = downloadHandler.texture; + texture = ((DownloadHandlerTexture)webRequest.downloadHandler).texture; if (texture == null) { @@ -579,27 +573,45 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) } finally { - downloadHandler.Dispose(); + webRequest.downloadHandler?.Dispose(); } texture.name = Path.GetFileNameWithoutExtension(cachePath); return texture; } + [Obsolete("Use new overload with debug support")] + public static async Task DownloadAudioClipAsync( + string url, + AudioType audioType, + RestParameters parameters = null, + CancellationToken cancellationToken = default) + { + return await DownloadAudioClipAsync(url, audioType, httpMethod: UnityWebRequest.kHttpVerbGET, parameters: parameters, cancellationToken: cancellationToken); + } + /// /// Download a from the provided . /// /// The url to download the from. /// to download. /// Optional, file name to download (including extension). + /// Optional, must be either GET or POST. + /// Optional, json payload. Only OR can be supplied. + /// Optional, raw byte payload. Only OR can be supplied. /// Optional, . + /// Optional, debug http request. /// Optional, . /// A new instance. public static async Task DownloadAudioClipAsync( string url, AudioType audioType, + string httpMethod = UnityWebRequest.kHttpVerbGET, string fileName = null, + string jsonData = null, + byte[] payload = null, RestParameters parameters = null, + bool debug = false, CancellationToken cancellationToken = default) { await Awaiters.UnityMainThread; @@ -627,21 +639,53 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) url = cachePath; } - using var webRequest = UnityWebRequestMultimedia.GetAudioClip(url, audioType); - parameters ??= new RestParameters(); - parameters.DisposeDownloadHandler = false; - var response = await webRequest.SendAsync(parameters, cancellationToken); + UploadHandler uploadHandler = null; + using var downloadHandler = new DownloadHandlerAudioClip(url, audioType); - if (!response.Successful) + if (httpMethod == UnityWebRequest.kHttpVerbPOST) { - throw new RestException(response, $"Failed to download audio clip from \"{url}\"!"); + if (!string.IsNullOrWhiteSpace(jsonData)) + { + if (payload != null) + { + throw new ArgumentException($"{nameof(payload)} and {nameof(jsonData)} cannot be supplied in the same request. Choose either one or the other.", nameof(jsonData)); + } + + payload = new UTF8Encoding().GetBytes(jsonData); + + var jsonHeaders = new Dictionary + { + { "Content-Type", "application/json" } + }; + + if (parameters is { Headers: not null }) + { + foreach (var header in parameters.Headers) + { + jsonHeaders.Add(header.Key, header.Value); + } + } + + if (parameters != null) + { + parameters.Headers = jsonHeaders; + } + } + + uploadHandler = new UploadHandlerRaw(payload); } AudioClip clip; - var downloadHandler = (DownloadHandlerAudioClip)webRequest.downloadHandler; + parameters ??= new RestParameters(); + parameters.DisposeUploadHandler = false; + parameters.DisposeDownloadHandler = false; + using var webRequest = new UnityWebRequest(url, httpMethod, downloadHandler, uploadHandler); try { + var response = await webRequest.SendAsync(parameters, cancellationToken); + response.Validate(debug); + if (!isCached) { await Cache.WriteCacheItemAsync(downloadHandler.data, cachePath, cancellationToken); @@ -650,16 +694,15 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) await Awaiters.UnityMainThread; clip = downloadHandler.audioClip; - if (clip == null || - clip.loadState == AudioDataLoadState.Failed || - clip.loadState == AudioDataLoadState.Unloaded) + if (clip == null) { - throw new RestException(response, $"Failed to load audio clip from \"{url}\"!"); + throw new RestException(response, $"Failed to download audio clip from \"{url}\"!"); } } finally { downloadHandler.Dispose(); + uploadHandler?.Dispose(); } clip.name = Path.GetFileNameWithoutExtension(cachePath); @@ -667,7 +710,7 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) } /// - /// Download a from the provided . + /// Stream a from the provided . /// /// The url to download the from. /// to download. @@ -680,7 +723,7 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) /// Optional, . /// Optional, debug http request. /// Optional, . - /// Raw downloaded bytes from the stream. + /// A new instance. public static async Task StreamAudioAsync( string url, AudioType audioType, @@ -748,9 +791,8 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) parameters.DisposeUploadHandler = false; parameters.DisposeDownloadHandler = false; using var downloadHandler = new DownloadHandlerAudioClip(url, audioType); - downloadHandler.streamAudio = true; // BUG: Due to a Unity bug this is actually totally non-functional... https://forum.unity.com/threads/downloadhandleraudioclip-streamaudio-is-ignored.699908/ + downloadHandler.streamAudio = true; // BUG: Due to a Unity bug this does not work with mp3s of indeterminate length. https://forum.unity.com/threads/downloadhandleraudioclip-streamaudio-is-ignored.699908/ using var webRequest = new UnityWebRequest(url, httpMethod, downloadHandler, uploadHandler); - IProgress progress = null; if (parameters.Progress != null) @@ -894,19 +936,31 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) #endif // UNITY_ADDRESSABLES + [Obsolete("use new overload with debug support")] + public static async Task DownloadFileAsync( + string url, + string fileName = null, + RestParameters parameters = null, + CancellationToken cancellationToken = default) + { + return await DownloadFileAsync(url, fileName, parameters, false, cancellationToken); + } + /// /// Download a file from the provided . /// /// The url to download the file from. /// Optional, file name to download (including extension). /// Optional, . + /// Optional, debug http request. /// Optional, . /// The path to the downloaded file. public static async Task DownloadFileAsync( - string url, - string fileName = null, - RestParameters parameters = null, - CancellationToken cancellationToken = default) + string url, + string fileName = null, + RestParameters parameters = null, + bool debug = false, + CancellationToken cancellationToken = default) { await Awaiters.UnityMainThread; @@ -925,12 +979,7 @@ public static bool TryGetFileNameFromUrl(string url, out string fileName) fileDownloadHandler.removeFileOnAbort = true; webRequest.downloadHandler = fileDownloadHandler; var response = await webRequest.SendAsync(parameters, cancellationToken); - - if (!response.Successful) - { - throw new RestException(response, $"Failed to download file from \"{url}\"!"); - } - + response.Validate(debug); return filePath; } diff --git a/package.json b/package.json index aede2db..6df5897 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "displayName": "Utilities.Rest", "description": "This package contains useful RESTful utilities for the Unity Game Engine.", "keywords": [], - "version": "2.3.1", + "version": "2.4.0", "unity": "2021.3", "documentationUrl": "https://github.com/RageAgainstThePixel/com.utilities.rest#documentation", "changelogUrl": "https://github.com/RageAgainstThePixel/com.utilities.rest/releases",