Easy HTTP (POST) communication with UnityWebRequest
thank you for your hard work.
This is Matsuyama from the System Development Office.
This time, I will write about HTTP (POST) communication using UnitWebRequest.
I feel like it's too late, but I only implemented communication via www, so I'll say it again ^^;
What to make
・HTTP (POST) communication with UnitWebRequst
・Requests and responses are in JSON format
・Simple with the assumption that multiple communication APIs will be created
*Created with Unity 2019.3.5f1
JSON
First, regarding JSON, we will implement it using Unity's JsonUtility.
JsonUtility is a Json parser provided by Unity that
can easily serialize Serializable classes and structures.
Although there are some limitations such as not supporting the Dictionary type, it seems to be better than other Json parsers in terms of performance.
Serialize to Json format
UnityWebRequest
This is the main communication process.
You can handle HTTP requests and responses with UnityWebRequest.
UnityWebRequest
The process itself was quite simple.
Generate UnityWebRequest in POST format and set request parameters in json format.
// Set HTTP (POST) information var req = new UnityWebRequest(url, "POST"); req.uploadHandler = (UploadHandler)new UploadHandlerRaw(postData); req.downloadHandler = (DownloadHandler)new DownloadHandlerBuffer(); req. SetRequestHeader("Content-Type", "application/json");
One thing to note is that parameters cannot be passed as strings, so you should convert them to byte arrays.
// Convert request object to JSON (byte array) string reqJson = JsonUtility.ToJson(request); byte[] postData = System.Text.Encoding.UTF8.GetBytes(reqJson);
I'll submit a request when I'm ready.
// API communication (wait for completion) yield return req.SendWebRequest();
The communication result was determined to be successful because isNetworkError and isHttpError are both false.
The response is stored in downloadHandler in Json format (text).
// Communication result if (req.isNetworkError || req.isHttpError) // Failure { Debug.Log("Network error:" + req.error); } else // Success { Debug.Log("Succeeded:" + req .downloadHandler.text); }
API control
An image of creating an API class that defines requests and responses for each API using the communication processing described above as a base class.
Is it specifically like this?
Create request and response structures with Serializable attributes and define parameters.
The common part of the URL during communication is defined on the base class side, so define the API name at the end.
using System; using System.Collections.Generic; namespace Api { ///<summary> /// API sample B ///</summary> public class SampleB : Web.ApiBase { public const string Name = "Test/SampleB"; ///<summary> /// Request parameters ///</summary> [Serializable] public struct Request { public string userId; public List<int> values; } public Request request; ///<summary> /// Response parameters ///</summary> [Serializable] public struct Response { public int count; public List<int> values; } public Response response; } }
How to use
First, generate the API class described above.
private Api.SampleB apiB; private Web.ApiBase.Result result; private void Start() { // Communication class generation apiB = new Api.SampleB(); // API communication sendApiB(); }
After specifying the API name, set the values to be passed to the request structure.
It is serialized into JSON format in the method Send() and communicated via HTTP (POST) using UnityWebRequest.
Receive the communication completion in the callback and deserialize it to the response structure.
Originally, I would write processing according to the content of the response, but since this is a sample, I just output it to the console.
///<summary> /// API sample B communication ///</summary> private void sendApiB() { // Set endpoint apiB.EndPoint = Api.SampleB.Name; // Set request parameters apiB.request.userId = "beyondB"; apiB.request.values = new List<int> () { 1, 10, 100, 1000 }; // Communication apiB.Send<Api.SampleB.Request> (ref apiB.request, result => { // Result if (result.isSucceeded) // Success { // Expand response apiB.response = apiB.Response<Api.SampleB.Response> (); // Check the contents Debug.Log("SampleB Succeed!!"); Debug.Log(" count : " + apiB.response.count); foreach(var v in apiB.response.values) { Debug.Log (" val : " + v); } } else // Failure { Debug.Log("SampleB Failed : " + result.error); } }); }
summary
In this way, I was able to write HTTP communication processing quite simply.
I think it can withstand practical use for the time being.
Since it is a communication process, it will not work without a server-side implementation, but I will upload the sample code on GitHub just in case.
Unity sample
Since the base class of the sample does not inherit MonoBehaviour, coroutines could not be used as is.
Please use this as a reference.
Using coroutines in classes that do not inherit MonoBehavior
lastly
I have opened the system development service site "SEKARAKU Lab" to which I belong.
Beyond is a one-stop service for everything from server design and construction to operation, so if you have any trouble with server-side development, please feel free to contact us.
SEKARAKU Lab: [https://sekarakulab.beyondjapan.com/](https://sekarakulab.beyondjapan.com/)
Well, that's all for now.