using System;
using System.Text;
using UnityEngine.Networking;
namespace UnityEngine.ResourceManagement.Util
{
///
/// Utility class for extracting information from UnityWebRequests.
///
public class UnityWebRequestUtilities
{
///
/// Determines if a web request resulted in an error.
///
/// The web request.
///
/// True if a web request resulted in an error.
public static bool RequestHasErrors(UnityWebRequest webReq, out UnityWebRequestResult result)
{
result = null;
if (webReq == null || !webReq.isDone)
return false;
#if UNITY_2020_1_OR_NEWER
switch (webReq.result)
{
case UnityWebRequest.Result.InProgress:
case UnityWebRequest.Result.Success:
return false;
case UnityWebRequest.Result.ConnectionError:
case UnityWebRequest.Result.ProtocolError:
case UnityWebRequest.Result.DataProcessingError:
result = new UnityWebRequestResult(webReq);
return true;
default:
throw new NotImplementedException($"Cannot determine whether UnityWebRequest succeeded or not from result : {webReq.result}");
}
#else
var isError = webReq.isHttpError || webReq.isNetworkError;
if (isError)
result = new UnityWebRequestResult(webReq);
return isError;
#endif
}
///
/// Indicates if the requested AssetBundle is downloaded.
///
/// The object returned from sending the web request.
/// Returns true if the AssetBundle is downloaded.
public static bool IsAssetBundleDownloaded(UnityWebRequestAsyncOperation op)
{
#if ENABLE_ASYNC_ASSETBUNDLE_UWR
var handler = (DownloadHandlerAssetBundle)op.webRequest.downloadHandler;
if (handler != null && handler.autoLoadAssetBundle)
return handler.isDownloadComplete;
#endif
return op.isDone;
}
}
///
/// Container class for the result of a unity web request.
///
public class UnityWebRequestResult
{
///
/// Creates a new instance of .
///
/// The unity web request.
public UnityWebRequestResult(UnityWebRequest request)
{
string error = request.error;
#if UNITY_2020_1_OR_NEWER
if (request.result == UnityWebRequest.Result.DataProcessingError && request.downloadHandler != null)
{
// https://docs.unity3d.com/ScriptReference/Networking.DownloadHandler-error.html
// When a UnityWebRequest ends with the result, UnityWebRequest.Result.DataProcessingError, the message describing the error is in the download handler
error = $"{error} : {request.downloadHandler.error}";
}
Result = request.result;
#endif
Error = error;
ResponseCode = request.responseCode;
Method = request.method;
Url = request.url;
}
/// Provides a new string object describing the result.
/// A newly allocated managed string.
public override string ToString()
{
var sb = new StringBuilder();
#if UNITY_2020_1_OR_NEWER
sb.AppendLine($"{Result} : {Error}");
#else
if (!string.IsNullOrEmpty(Error))
sb.AppendLine(Error);
#endif
if (ResponseCode > 0)
sb.AppendLine($"ResponseCode : {ResponseCode}, Method : {Method}");
sb.AppendLine($"url : {Url}");
return sb.ToString();
}
///
/// A string explaining the error that occured.
///
public string Error { get; set; }
///
/// The numeric HTTP response code returned by the server, if any.
/// See documentation for more details.
///
public long ResponseCode { get; }
#if UNITY_2020_1_OR_NEWER
///
/// The outcome of the request.
///
public UnityWebRequest.Result Result { get; }
#endif
///
/// The HTTP verb used by this UnityWebRequest, such as GET or POST.
///
public string Method { get; }
///
/// The target url of the request.
///
public string Url { get; }
///
/// Determines if the web request can be sent again based on its error.
///
/// Returns true if the web request can be sent again.
public bool ShouldRetryDownloadError()
{
if (string.IsNullOrEmpty(Error))
return true;
if (Error == "Request aborted" ||
Error == "Unable to write data" ||
Error == "Malformed URL" ||
Error == "Out of memory" ||
Error == "Encountered invalid redirect (missing Location header?)" ||
Error == "Cannot modify request at this time" ||
Error == "Unsupported Protocol" ||
Error == "Destination host has an erroneous SSL certificate" ||
Error == "Unable to load SSL Cipher for verification" ||
Error == "SSL CA certificate error" ||
Error == "Unrecognized content-encoding" ||
Error == "Request already transmitted" ||
Error == "Invalid HTTP Method" ||
Error == "Header name contains invalid characters" ||
Error == "Header value contains invalid characters" ||
Error == "Cannot override system-specified headers"
#if UNITY_2022_1_OR_NEWER
|| Error == "Insecure connection not allowed"
#endif
)
return false;
/* Errors that can be retried:
"Unknown Error":
"No Internet Connection"
"Backend Initialization Error":
"Cannot resolve proxy":
"Cannot resolve destination host":
"Cannot connect to destination host":
"Access denied":
"Generic/unknown HTTP error":
"Unable to read data":
"Request timeout":
"Error during HTTP POST transmission":
"Unable to complete SSL connection":
"Redirect limit exceeded":
"Received no data in response":
"Destination host does not support SSL":
"Failed to transmit data":
"Failed to receive data":
"Login failed":
"SSL shutdown failed":
"Redirect limit is invalid":
"Not implemented":
"Data Processing Error, see Download Handler error":
*/
return true;
}
}
}