public void _request(string endPoint, RequestData requestData, bool includeSession = true, bool isResend = false)
        {
            if (isSending)
            {
                return;
            }

            //settings
            isSending               = true;
            LastRequest             = new LastRequest();
            LastRequest.EndPoint    = endPoint;
            LastRequest.RequestData = requestData;

            //add request data params
            requestData.timestamp  = PredictedServerTimestamp;
            requestData.version    = Version;
            requestData.versionKey = VersionKey;

            if (includeSession)
            {
                requestData.session = user.session;
            }

            nonce++;
            if (!isResend)
            {
                requestData.cacheKey = nonce.ToString();
            }
            else
            {
                LastRequest.IsResend = true;
            }

            // ------

            string json = JsonUtility.ToJson(requestData);

            if (localSendInvalidRequestData)
            {
                json = "hahahaha";
            }
            Debug.Log(json);

            // post
            Byte[] payload          = _encryptionHelper.StringToBytes(json);
            Byte[] payloadEncrypted = _encryptionHelper.Encrypt(payload, nonce);
            string payloadBase64    = _encryptionHelper.BytesToBase64(payloadEncrypted);
            var    postForm         = new RawJsonForm();

            postForm.AddField("payloadBase64", payloadBase64);

            // signature
            Byte[] nonceByte   = _encryptionHelper.GetNonceBytes(nonce);
            Byte[] digest      = md5.ComputeHash(payloadEncrypted);
            Byte[] signMessage = new byte[8 + digest.Length];
            nonceByte.CopyTo(signMessage, 0);
            digest.CopyTo(signMessage, 8);
            Byte[] signedByte   = _encryptionHelper.SignMessage(signMessage);
            string signedBase64 = _encryptionHelper.BytesToBase64(signedByte);

            // query
            Dictionary <string, string> queryDict = new Dictionary <string, string>();

            queryDict.Add("signedBase64", signedBase64);
            queryDict.Add("token", token);

            // testing
            if (remoteTimeout)
            {
                queryDict.Add("remoteTimeout", "true");
            }

            if (remoteSendInvalidPayload)
            {
                queryDict.Add("remoteSendInvalidPayload", "true");
            }

            if (localSendInvalidSignBase64)
            {
                queryDict["signedBase64"] = "aaaaaa";
            }

            var query = getQuery(queryDict);


            // send request
            var url = $"{Host}{endPoint}?{query}";

            Debug.Log(url);
            HTTPRequest request = new HTTPRequest(new Uri(url), HTTPMethods.Post, OnRespond);

            request.SetForm(postForm);
            request.Timeout = TimeSpan.FromSeconds(Timeout);
            request.Send();
        }