public unsafe static T Fetch <T>(string id, Action <ApiContainer> onSuccess = null, Action <ApiContainer> onFailure = null, bool disableCache = false) where T : ApiModel, ApiCacheObject, new() { id = id?.Trim(); T val = new T(); val.id = id; T model = (T)val; if (!disableCache && ApiCache.Fetch(id, ref *(T *)(&model))) { if (onSuccess != null) { UpdateDelegator.Dispatch(delegate { onSuccess(new ApiModelContainer <T>((T)model)); }); } return((T)model); } model.Fetch(onSuccess, onFailure, null, disableCache); return((T)model); }
protected virtual void PostOrPut(Action <ApiContainer> onSuccess, Action <ApiContainer> onFailure, PostOrPutSelect select, Dictionary <string, object> requestParams = null) { if (string.IsNullOrEmpty(Endpoint)) { Logger.LogErrorFormat(DebugLevel.API, "Cannot save to null endpoint"); } else { if (requestParams == null) { requestParams = ExtractApiFields(); } if (APIUser.CurrentUser == null || !APIUser.CurrentUser.hasSuperPowers) { List <KeyValuePair <string, object> > list = (from kvp in requestParams where IsAdminWritableOnly(FindProperty(kvp.Key)) select kvp).ToList(); foreach (KeyValuePair <string, object> item in list) { requestParams.Remove(item.Key); } } List <KeyValuePair <string, object> > list2 = (from kvp in requestParams where IsApiWritableOnly(FindProperty(kvp.Key)) select kvp).ToList(); foreach (KeyValuePair <string, object> item2 in list2) { requestParams.Remove(item2.Key); } Action <ApiContainer> onSuccess2 = delegate(ApiContainer c) { ApiCache.Save(c.Model.id, c.Model, andClone: true); if (onSuccess != null) { onSuccess(c); } }; switch (select) { case PostOrPutSelect.Auto: if (!string.IsNullOrEmpty(id)) { SendPutRequest(new ApiContainer { OnSuccess = onSuccess2, OnError = onFailure, Model = this }, requestParams); } else { API.SendPostRequest(Endpoint, MakeModelContainer(onSuccess2, onFailure), requestParams); } break; case PostOrPutSelect.Post: API.SendPostRequest(Endpoint, MakeModelContainer(onSuccess2, onFailure), requestParams); break; case PostOrPutSelect.Put: { ApiModel target = null; if (ApiCache.Fetch(GetType(), id + "_copy", ref target, 3.40282347E+38f)) { foreach (KeyValuePair <string, object> item3 in target.ExtractApiFields()) { if (requestParams.ContainsKey(item3.Key)) { if (typeof(IList).IsAssignableFrom(item3.Value.GetType()) && typeof(IList).IsAssignableFrom(requestParams[item3.Key].GetType())) { IList a = item3.Value as IList; IList b = requestParams[item3.Key] as IList; if (!b.Cast <object>().Any((object bo) => !a.Contains(bo)) && !a.Cast <object>().Any((object ao) => !b.Contains(ao))) { requestParams.Remove(item3.Key); } } else if (item3.Value.Equals(requestParams[item3.Key])) { requestParams.Remove(item3.Key); } } } } SendPutRequest(new ApiContainer { OnSuccess = onSuccess2, OnError = onFailure, Model = this }, requestParams); break; } } } }
public virtual void Get(Action <ApiContainer> onSuccess = null, Action <ApiContainer> onFailure = null, Dictionary <string, object> parameters = null, bool disableCache = false) { if (string.IsNullOrEmpty(id) && string.IsNullOrEmpty(Endpoint)) { if (onFailure != null) { onFailure(new ApiContainer { Error = "Fetch called with null id." }); } } else { string key = MakeRequestEndpoint() + Json.Encode(parameters); if (activeRequests.ContainsKey(key)) { ApiContainer apiContainer = activeRequests[key]; Action <ApiContainer> originalSuccess = apiContainer.OnSuccess; Action <ApiContainer> onSuccess2 = delegate(ApiContainer c) { if (activeRequests.ContainsKey(key)) { activeRequests.Remove(key); } try { if (onSuccess != null) { onSuccess(c); } } catch (Exception ex4) { Debug.LogException(ex4); } if (originalSuccess != null) { originalSuccess(c); } }; Action <ApiContainer> originalError = apiContainer.OnError; Action <ApiContainer> onError = delegate(ApiContainer c) { if (activeRequests.ContainsKey(key)) { activeRequests.Remove(key); } try { if (onFailure != null) { onFailure(c); } } catch (Exception ex3) { Debug.LogException(ex3); } if (originalError != null) { originalError(c); } }; apiContainer.OnSuccess = onSuccess2; apiContainer.OnError = onError; } else { Action <ApiContainer> onSuccess3 = delegate(ApiContainer c) { if (activeRequests.ContainsKey(key)) { activeRequests.Remove(key); } try { if (onSuccess != null) { onSuccess(c); } } catch (Exception ex2) { Debug.LogException(ex2); } ApiCache.Save(c.Model.id, c.Model, andClone: true); }; Action <ApiContainer> onFailure2 = delegate(ApiContainer c) { if (activeRequests.ContainsKey(key)) { activeRequests.Remove(key); } try { if (onFailure != null) { onFailure(c); } } catch (Exception ex) { Debug.LogException(ex); } }; ApiContainer apiContainer2 = MakeModelContainer(onSuccess3, onFailure2); activeRequests.Add(key, apiContainer2); SendGetRequest(apiContainer2, parameters, disableCache); } } }
private static void SendRequestInternal(string endpoint, HTTPMethods method, ApiContainer responseContainer = null, Dictionary <string, object> requestParams = null, bool authenticationRequired = true, bool disableCache = false, float cacheLifetime = 3600f, int retryCount = 2, CredentialsBundle credentials = null) { if (responseContainer == null) { responseContainer = new ApiContainer(); } if (API_ONLINE_MODE == ApiOnlineMode.Offline) { SendOfflineRequest(endpoint, method, responseContainer, requestParams); } else { if (API_ONLINE_MODE == ApiOnlineMode.Uninitialized) { Debug.LogError((object)"Api Web Request send before online mode is initialized."); } string apiUrl = GetApiUrl(); Action action = delegate { string uri = apiUrl + endpoint; UriBuilder baseUri = new UriBuilder(uri); if (!string.IsNullOrEmpty(ApiKey)) { AppendQuery(ref baseUri, "apiKey=" + ApiKey); } if (API_ORGANIZATION == null) { throw new Exception("ApiModel does not have it's organization set!"); } AppendQuery(ref baseUri, "organization=" + API_ORGANIZATION); string text = null; if (requestParams != null) { if (method == HTTPMethods.Get) { foreach (KeyValuePair <string, object> requestParam in requestParams) { string text2 = null; AppendQuery(ref baseUri, string.Concat(str2: (!(requestParam.Value is string)) ? ((!typeof(List <>).IsAssignableFrom(requestParam.Value.GetType())) ? Json.Encode(requestParam.Value) : Json.Encode((requestParam.Value as IList).Cast <object>().ToArray())) : (requestParam.Value as string), str0: requestParam.Key, str1: "=")); } } else { text = Json.Encode(requestParams); } } string uriPath = baseUri.Uri.PathAndQuery; bool useCache = !disableCache && method == HTTPMethods.Get; ApiCache.CachedResponse cachedResponse = (!useCache) ? null : ApiCache.GetOrClearCachedResponse(baseUri.Uri.PathAndQuery, cacheLifetime); if (cachedResponse != null) { Logger.LogFormat(DebugLevel.API, "Using cached {0} request to {1}", method, baseUri.Uri); try { if (responseContainer.OnComplete(success: true, baseUri.Uri.PathAndQuery, 200, string.Empty, () => cachedResponse.Data, () => cachedResponse.DataAsText, cachedResponse.Timestamp)) { responseContainer.OnSuccess(responseContainer); } else { Logger.LogErrorFormat(DebugLevel.API, "Something went wrong re-serving data from cache for {0}", baseUri.Uri); } } catch (Exception ex) { Debug.LogException(ex); } } else if (method == HTTPMethods.Get && activeRequests.ContainsKey(uriPath)) { Logger.LogFormat(DebugLevel.API, "Piggy-backing {0} request to {1}", method, baseUri.Uri); OnRequestFinishedDelegate originalCallback = activeRequests[uriPath].Callback; activeRequests[uriPath].Callback = delegate(HTTPRequest req, HTTPResponse resp) { if (activeRequests.ContainsKey(uriPath)) { activeRequests.Remove(uriPath); } if (originalCallback != null) { originalCallback(req, resp); } try { APIResponseHandler.HandleReponse(0, req, resp, responseContainer, retryCount, useCache); } catch (Exception ex2) { Debug.LogException(ex2); } }; } else { int requestId = ++lastRequestId; Logger.LogFormat(DebugLevel.API, "[{0}] Sending {1} request to {2}", requestId, method, baseUri.Uri); HTTPRequest hTTPRequest = new HTTPRequest(baseUri.Uri, delegate(HTTPRequest req, HTTPResponse resp) { if (activeRequests.ContainsKey(uriPath)) { activeRequests.Remove(uriPath); } APIResponseHandler.HandleReponse(requestId, req, resp, responseContainer, retryCount, useCache); }); if (authenticationRequired) { if (credentials != null) { hTTPRequest.Credentials = new Credentials(AuthenticationTypes.Basic, credentials.Username, credentials.Password); } else if (!string.IsNullOrEmpty(ApiCredentials.GetAuthToken())) { List <Cookie> cookies = hTTPRequest.Cookies; cookies.Add(new Cookie("auth", ApiCredentials.GetAuthToken())); hTTPRequest.Cookies = cookies; } else { Logger.LogErrorFormat(DebugLevel.API, "No credentials!"); } } hTTPRequest.AddHeader("X-Requested-With", "XMLHttpRequest"); hTTPRequest.AddHeader("X-MacAddress", DeviceID); if (Tools.isClient) { hTTPRequest.AddHeader("X-Client-Version", Tools.ClientVersion); } else { hTTPRequest.AddHeader("X-SDK-Version", Tools.ClientVersion); } hTTPRequest.AddHeader("X-Platform", Tools.Platform); hTTPRequest.AddHeader("Content-Type", (method != 0) ? "application/json" : "application/x-www-form-urlencoded"); hTTPRequest.AddHeader("Origin", "vrchat.com"); hTTPRequest.MethodType = method; hTTPRequest.ConnectTimeout = TimeSpan.FromSeconds(20.0); hTTPRequest.Timeout = TimeSpan.FromSeconds(60.0); hTTPRequest.EnableTimoutForStreaming = true; if (!string.IsNullOrEmpty(text)) { hTTPRequest.RawData = Encoding.UTF8.GetBytes(text); } if (method == HTTPMethods.Get) { activeRequests.Add(uriPath, hTTPRequest); } hTTPRequest.DisableCache = true; hTTPRequest.Send(); } string key = endpoint.ToLower().Split('?')[0]; if (!EndpointAccessTimes.ContainsKey(key)) { EndpointAccessTimes.Add(key, new EndpointAccessEntry { count = 1, time = Time.get_realtimeSinceStartup() }); } else { EndpointAccessTimes[key].time = Time.get_realtimeSinceStartup(); EndpointAccessTimes[key].count++; } }; if (endpoint != "config" && string.IsNullOrEmpty(ApiKey) && !IsOffline()) { FetchApiKey(action); } else { action(); } } }
public static void HandleReponse(int requestId, HTTPRequest req, HTTPResponse resp, ApiContainer responseContainer, int retryCount = 0, bool useCache = false) { if (responseContainer == null) { Logger.LogError("ResponseContainer was null!"); } else if (req == null) { responseContainer.Error = "The request was null."; if (responseContainer.OnError != null) { responseContainer.OnError(responseContainer); } } else if (resp == null) { responseContainer.Error = "The response was null."; if (responseContainer.OnError != null) { responseContainer.OnError(responseContainer); } } else { string text3; string text2; string text; string empty; string text4 = text3 = (text2 = (text = (empty = string.Empty))); try { text4 = ((resp != null) ? resp.StatusCode.ToString() : "null"); text3 = ((req != null) ? req.MethodType.ToString() : "null"); text2 = ((req != null) ? req.Uri.ToString() : "null"); text = ((resp != null) ? resp.DataAsText.Replace("{", "{{").Replace("}", "}}") : "null"); empty = ((req.RawData != null) ? Encoding.UTF8.GetString(req.RawData).Replace("{", "{{").Replace("}", "}}") : string.Empty); } catch (Exception ex) { Logger.LogErrorFormat("Exception in reading response: {0}\n{1}", new object[2] { ex.Message, ex.StackTrace }); responseContainer.Error = "Bad response data."; if (responseContainer.OnError != null) { responseContainer.OnError(responseContainer); } return; IL_01ca :; } if (req.State == HTTPRequestStates.Finished && (resp == null || resp.StatusCode < 200 || resp.StatusCode >= 400)) { req.State = HTTPRequestStates.Error; } responseContainer.Cookies = ((resp != null && resp.Cookies != null) ? (from c in resp.Cookies where c != null select new KeyValuePair <string, string>(c.Name, c.Value)).ToDictionary((KeyValuePair <string, string> t) => t.Key, (KeyValuePair <string, string> t) => t.Value) : new Dictionary <string, string>()); try { switch (req.State) { case HTTPRequestStates.Finished: responseContainer.OnComplete(resp.IsSuccess, req.Uri.PathAndQuery, resp.StatusCode, resp.Message, () => resp.Data, () => resp.DataAsText); if (!responseContainer.IsValid) { RetryRequest(requestId, req, resp, responseContainer, --retryCount, useCache, string.Empty); } else { if (useCache && req.MethodType == HTTPMethods.Get) { ApiCache.CacheResponse(req.Uri.PathAndQuery, resp.Data); } if (responseContainer.OnSuccess != null) { responseContainer.OnSuccess(responseContainer); } } break; default: { string text5 = (req.Exception == null) ? "No Exception" : req.Exception.Message; Logger.LogErrorFormat(DebugLevel.API, "[{0}, {1}, {2}, {3}] Request Finished with Error!\n{4}\n{5}\n{6}\n{7}", requestId, text4, text3, retryCount, text2, empty, text5, text); responseContainer.OnComplete(success: false, req.Uri.PathAndQuery, resp.StatusCode, resp.Message, () => resp.Data, () => resp.DataAsText); if (resp.StatusCode >= 400 && resp.StatusCode < 500) { retryCount = 0; } RetryRequest(requestId, req, resp, responseContainer, --retryCount, useCache, string.Empty); break; } case HTTPRequestStates.Aborted: Logger.LogErrorFormat(DebugLevel.API, "[{0}, {1}, {2}, {3}] Request Request Aborted!\n{4}\n{5}", requestId, text4, text3, retryCount, text2, text); responseContainer.Error = "The request was cancelled."; if (responseContainer.OnError != null) { responseContainer.OnError(responseContainer); } break; case HTTPRequestStates.ConnectionTimedOut: Logger.LogErrorFormat(DebugLevel.API, "[{0}, {1}, {2}, {3}] Connection Timed Out!\n{4}\n{4}", requestId, text4, text3, retryCount, text2, text); RetryRequest(requestId, req, resp, responseContainer, --retryCount, useCache, "The request timed out."); break; case HTTPRequestStates.TimedOut: Logger.LogErrorFormat(DebugLevel.API, "[{0}, {1}, {2}, {3}] Processing the request Timed Out!\n{4}\n{5}", requestId, text4, text3, retryCount, text2, text); RetryRequest(requestId, req, resp, responseContainer, --retryCount, useCache, "The request timed out."); break; } } catch (Exception ex2) { Logger.LogErrorFormat("Exception handling {0}: {1}\n{2}", req.State, ex2.Message, ex2.StackTrace); } } }