Skip to content

Instantly share code, notes, and snippets.

@petitviolet
Created September 7, 2022 12:02
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save petitviolet/d6be3158e77633b25e2facd467d46d44 to your computer and use it in GitHub Desktop.
Save petitviolet/d6be3158e77633b25e2facd467d46d44 to your computer and use it in GitHub Desktop.
Json over HTTP in Unity C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Cysharp.Threading.Tasks;
using UnityEngine;
using UnityEngine.Networking;
namespace MyNamespace
{
public class JsonHttp
{
public class HttpError : Exception
{
public readonly long StatusCode;
public HttpError(long statusCode, string message) : base(message)
{
StatusCode = statusCode;
}
public HttpError(long statusCode, string message, Exception baseException) : base(message, baseException)
{
StatusCode = statusCode;
}
override public string ToString()
{
return $"HttpError(statusCode: {StatusCode}, message: {Message})";
}
}
private readonly Uri _baseUri;
public JsonHttp(string baseUri)
{
this._baseUri = new Uri(baseUri);
}
public async Task<Result<T, HttpError>> Get<T>(string path, Dictionary<string, string> query = null, Dictionary<string, string> headers = null, int timeoutSec = 3)
{
var urlParameter = query != null ? $"?{String.Join("&", query.Select(pair => pair.Key + "=" + pair.Value))}" : "";
var url = new Uri(_baseUri, $"{path}{urlParameter}");
Debug.Log($"GET url: {url}, query: {query}");
var request = UnityWebRequest.Get(url);
return await ProcessJsonRequest<T>(request, headers, timeoutSec);
}
public async Task<Result<T, HttpError>> Post<T>(string path, object requestBody, Dictionary<string, string> headers = null, int timeoutSec = 3)
{
var url = new Uri(_baseUri, path);
var body = JsonUtility.ToJson(requestBody);
Debug.Log($"POST url: {url}, body: {body}");
var request = new UnityWebRequest(url, "POST");
request.uploadHandler = new UploadHandlerRaw(Encoding.UTF8.GetBytes(body));
request.downloadHandler = new DownloadHandlerBuffer();
return await ProcessJsonRequest<T>(request, headers, timeoutSec);
}
private async Task<Result<T, HttpError>> ProcessJsonRequest<T>(UnityWebRequest request, Dictionary<string, string> headers, int timeoutSec)
{
request.timeout = timeoutSec;
request.SetRequestHeader("Content-Type", "application/json");
request.SetRequestHeader("Accept", "application/json");
if (headers != null)
{
foreach (var entry in headers)
{
request.SetRequestHeader(entry.Key, entry.Value);
}
}
try
{
await request.SendWebRequest().WithCancellation(CancellationToken.None);
var text = request.downloadHandler.text;
Debug.Log($"result: {request.result}, responseCode: {request.responseCode}, body: {text}, error: {request.error}");
// Consider the request succeeded only when it gets 200-399 HTTP status code
if (request.result == UnityWebRequest.Result.Success && request.responseCode >= 200 && request.responseCode < 400)
{
var body = JsonUtility.FromJson<T>(text);
return Result<T, HttpError>.Succeeded(body);
}
else
{
return Result<T, HttpError>.Failed(new HttpError(request.responseCode, request.error.Length > 0 ? request.error : text));
}
}
catch (Exception e)
{
return Result<T, HttpError>.Failed(new HttpError(request.responseCode, $"ProcessJsonRequest failed due to {e}"));
}
}
}
}
@petitviolet
Copy link
Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment