Last active
November 15, 2024 05:53
-
-
Save bawahakim/69575e656078c6a74f1a6fe75dd02bcd to your computer and use it in GitHub Desktop.
Allows using UnityWebRequest with an IHttpClient interface, for example with nswag
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Depends on UniTask to support cancellation token and GetAwaiter: https://github.com/Cysharp/UniTask | |
// Otherwise, the code can be adapted using https://gist.github.com/krzys-h/9062552e33dd7bd7fe4a6c12db109a1a | |
using System; | |
using System.Linq; | |
using System.Net; | |
using System.Net.Http; | |
using System.Net.Http.Headers; | |
using System.Threading; | |
using System.Threading.Tasks; | |
using Cysharp.Threading.Tasks; | |
using UnityEngine.Networking; | |
public interface IHttpClient { | |
public Uri BaseAddress { get; set; } | |
public HttpRequestHeaders DefaultRequestHeaders { get; } | |
public Task<HttpResponseMessage> SendAsync(HttpRequestMessage message, HttpCompletionOption option, | |
CancellationToken token); | |
public void Dispose(); | |
} | |
public class UnityWebRequestHttpClient : IHttpClient { | |
public UnityWebRequestHttpClient() { } | |
public UnityWebRequestHttpClient(string baseUri) { | |
BaseAddress = new Uri(baseUri); | |
} | |
public UnityWebRequestHttpClient(Uri baseUri) { | |
BaseAddress = baseUri; | |
} | |
public Uri BaseAddress { get; set; } | |
public HttpRequestHeaders DefaultRequestHeaders => _httpClient.DefaultRequestHeaders; | |
private readonly HttpClient _httpClient = new HttpClient(); | |
public async Task<HttpResponseMessage> SendAsync(HttpRequestMessage message, HttpCompletionOption option, | |
CancellationToken token) { | |
var content = await (message.Content?.ReadAsStringAsync() ?? Task.FromResult("")); | |
var webRequest = GetUnityWebRequest(message.Method.Method, message.RequestUri, content); | |
AppendHeaders(webRequest); | |
try { | |
await webRequest | |
.SendWebRequest() | |
.WithCancellation(cancellationToken: token); | |
} | |
catch (Exception) { | |
webRequest.Dispose(); | |
throw; | |
} | |
var responseMessage = CreateHttpResponseMessage(webRequest); | |
webRequest.Dispose(); | |
return responseMessage; | |
} | |
public void Dispose() { | |
_httpClient.Dispose(); | |
DefaultRequestHeaders.Clear(); | |
BaseAddress = null; | |
} | |
private UnityWebRequest GetUnityWebRequest(string method, Uri endpoint, string content = "") { | |
var requestUri = BaseAddress.AbsoluteUri + endpoint; | |
var webRequest = UnityWebRequest.Get(requestUri); | |
webRequest.method = method; | |
webRequest.disposeUploadHandlerOnDispose = true; | |
webRequest.disposeDownloadHandlerOnDispose = true; | |
if (!string.IsNullOrEmpty(content)) { | |
var data = new System.Text.UTF8Encoding().GetBytes(content); | |
webRequest.uploadHandler = new UploadHandlerRaw(data); | |
webRequest.SetRequestHeader("Content-Type", "application/json"); | |
} | |
return webRequest; | |
} | |
private void AppendHeaders(UnityWebRequest webRequest) { | |
using var enumerator = DefaultRequestHeaders.GetEnumerator(); | |
while (enumerator.MoveNext()) { | |
var (key, value) = enumerator.Current; | |
webRequest.SetRequestHeader(key, value.First()); | |
} | |
} | |
private HttpResponseMessage CreateHttpResponseMessage(UnityWebRequest webRequest) { | |
var response = new HttpResponseMessage(); | |
var responseContent = webRequest.downloadHandler?.text; | |
response.Content = new StringContent(responseContent); | |
response.StatusCode = (HttpStatusCode) webRequest.responseCode; | |
foreach (var (key, value) in webRequest.GetResponseHeaders()) { | |
switch (key.ToLower().Trim()) { | |
case "content-type": { | |
var trimmed = value.ToLower().Split(";").FirstOrDefault(); | |
response.Content.Headers.ContentType = new MediaTypeHeaderValue(trimmed); | |
break; | |
} | |
case "content-length": | |
response.Content.Headers.ContentLength = long.Parse(value); | |
break; | |
default: | |
response.Headers.Add(key, value); | |
break; | |
} | |
} | |
return response; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
It is possible to remove the Cysharp dependency by replacing
await webRequest.SendWebRequest().WithCancellation(cancellationToken: token);
with following: