After defining an endpoint the application logic (often also called business logic) has to be implemented for the endpoint to be useful.
All request information is supplied to the user code in the request variable:
using RestServer;
using UnityEngine;
public class Example : MonoBehaviour {
// Reference to the RestServer instance
public RestServer.RestServer server;
private void Start() {
server.EndpointCollection.RegisterEndpoint(HttpMethod.GET, "/position", (request) => {
var qp = request.QueryParameters // access ?a=b&c=d part
var qpd = request.QueryParametersDict // same as above, as dictionary
request.Headers; // Request Headers
request.Body // Access the request body directly as string
request.BodyBytes // Access the request body as byte array for binary requests
request.JsonBody</* Type */>() // Deserialize the request body as JSON
request.CreateResponse().SendAsync();
});
}
}
While it’s not the primary use case to handle binary data, the rest server implementation still provides various methods to handle binary data.
There are two variants mentioned here, more variants are described in the FAQ.
In this variant the request body is the uploaded file directly. This can easily be achieved when the client is a JavaScript application and/or a custom application where the request can be controlled completely. The binary body data can be accessed in the request via this method:
var data = request.BodyBytes
Multipart/form-data should be the default HTML upload method when using forms in browsers with binary data. It is also the most complicated as multiple files can be uploaded with the same request and the body follows a complicated structure. It is outside the scope of the rest server library to provide a full parser for this as there are already advanced open source libraries that do this.
Nevertheless, the rest server includes a very simple parser to parse very simple multipart/form-data requests. See the Static Content Example.
List<MultiFormDataElement> uploadData;
try {
uploadData = new SimpleMFDParser().Parse(request);
}
catch (SystemException e) {
request.CreateResponse().InternalServerError("No form data found.").SendAsync();
return;
}
var data = uploadData[0].Data;
Each request is executed in a separate Thread and Unity resources can’t be accessed directly. The ThreadingHelper
was
created to mitigate this fact.
The ThreadingHelper
can run synchronously, asynchronously and coroutine workloads in the Unity render thread.
In the synchronous case the request will wait until the Unity rendering thread has executed the workload and return
information back to the endpoint method.
The asynchronous method is executed on the next rendered frame in Unity main render thread and doesn’t block the endpoint
implementation.
In order to have an efficient Rest Server and Unity Rendering it is best to keep the amount of work inside the workload minimal.
Execute Sync example:
var position = ThreadingHelper.Instance.ExecuteSync(() => {
return transform.position;
});
Execute Async example:
ThreadingHelper.Instance.ExecuteAsync(() => {
transform.position += new Vector3(1.0f, 1.0f, 1.0f);
});
Execute Coroutine example:
void Start() {
server.EndpointCollection.RegisterEndpoint(HttpMethod.GET, "/position", request => {
ThreadingHelper.Instance.ExecuteAsyncCoroutine(Coroutine);
});
}
private IEnumerator Coroutine() {
yield return null;
}
See Multithreading for a deeper discussion.
Do not:
var position = ThreadingHelper.Instance.ExecuteAsync(() => {
transform.position += Vector3.up;
request.XXX; // Not allowed
});