Skip to content

Web Requests Framework

Mikhail Agapov edited this page Dec 11, 2023 · 5 revisions

General Structure

We are using a custom generic structure for performing Web Requests in an asynchronous way. It's located in DCL.WebRequests assembly.

Currently, the exposed API looks like this:

public interface IWebRequestController
    {        
        UniTask<GenericGetRequest> GetAsync(
            CommonArguments commonArguments,
            CancellationToken ct,
            string reportCategory = ReportCategory.GENERIC_WEB_REQUEST,
            WebRequestHeadersInfo? headersInfo = null,
            WebRequestSignInfo? signInfo = null);

        UniTask<GenericPostRequest> PostAsync(
            CommonArguments commonArguments,
            GenericPostArguments arguments,
            CancellationToken ct,
            string reportCategory = ReportCategory.GENERIC_WEB_REQUEST,
            WebRequestHeadersInfo? headersInfo = null,
            WebRequestSignInfo? signInfo = null);

        UniTask<GetTextureWebRequest> GetTextureAsync(
            CommonArguments commonArguments,
            GetTextureArguments args,
            CancellationToken ct,
            string reportCategory = ReportCategory.GENERIC_WEB_REQUEST,
            WebRequestHeadersInfo? headersInfo = null,
            WebRequestSignInfo? signInfo = null);
    }

Every type of request creates a strongly typed structure to define and restrain the set of possible operations. E.g. to prevent reading text from GetTexture request. This capability is not provided by Unity itself: it will just throw an exception.

The whole API is designed to provide an allocation-free way of setting parameters:

  • Everything is designed with Value Types unless it's restricted by Unity API itself
  • WebRequestHeadersInfo uses the pool and is disposed of automatically when a Web Request fails or succeeds

Common Arguments

public readonly URLAddress URL;
public readonly int AttemptsCount = 3;
public readonly int Timeout = 0;

Repetitions are handled inside the implementation of IWebRequestController. If needed (for test purposes) this behavior can be overridden.

Signing

Some requests require a signature to validate the identity of the caller. Those are sensitive APIs that should not be abused by third-party consumers.

The identity itself is provided by the IWeb3Authenticator implementation. Then with the capabilities of AuthChain and Nethereum Library x-identity-auth-chain-N headers are set in accordance.

For this to work the following structure should be provided as an argument to the request:

    public readonly struct WebRequestSignInfo
    {
        public readonly URLAddress SignUrl;

        public WebRequestSignInfo(URLAddress signUrl)
        {
            SignUrl = signUrl;
        }
    }

Common Response Parsing Scenarios

Our scenarios of handling responses are common, therefore, several utilities are presented to unify the approaches and get rid of potential boiler-plate code.

  • GenericDownloadHandlerUtils provides capabilities for generic Post and Get requests
    • OverwriteFromJson<T> - parse JSON into the existing object with Unity/Newtonsoft off/on the main thread
    • CreateFromJson<T> - create an object from JSON with Unity/Newtonsoft off/on the main thread
    • GetDataCopy() - produce a managed byte[]
    • Calling these methods will provide data and automatically release the underlying request
  • Texture creation from GetTextureWebRequest (can be further expanded to include Sprites creation)

Analytics

IWebRequestsAnalyticsContainer records currently ongoing requests. At the moment it's used just for counting and displaying the value in the Debug View via ShowWebRequestsCountersSystem but in the future can be expanded to hold additional information about requests.