/// <summary> /// Sends an HTTP request and checks for errors /// </summary> /// <param name="method">HTTP method to use</param> /// <param name="endpoint">API endpoint (fx. /users/@me)</param> /// <param name="payload">JSON content</param> private Response Send(Leaf.xNet.HttpMethod method, string endpoint, object payload = null) { string json = "{}"; if (payload != null) { if (payload.GetType() == typeof(string)) { json = (string)payload; } else { json = JsonConvert.SerializeObject(payload); } } bool isEndpoint = !endpoint.StartsWith("http"); if (isEndpoint) { endpoint = _discordClient.Config.ApiBaseUrl + endpoint; } bool hasData = method == Leaf.xNet.HttpMethod.POST || method == Leaf.xNet.HttpMethod.PATCH || method == Leaf.xNet.HttpMethod.PUT || method == Leaf.xNet.HttpMethod.DELETE; while (true) { try { string resp; int statusCode; if (_discordClient.Config.Proxy == null || _discordClient.Config.Proxy.Type == ProxyType.HTTP) { HttpClient client = new HttpClient(new HttpClientHandler() { Proxy = _discordClient.Config.Proxy == null ? null : new WebProxy(_discordClient.Config.Proxy.Host, _discordClient.Config.Proxy.Port) }); if (_discordClient.Token != null) { client.DefaultRequestHeaders.Add("Authorization", _discordClient.Token); } if (Fingerprint != null) { client.DefaultRequestHeaders.Add("X-Fingerprint", Fingerprint); } client.DefaultRequestHeaders.Add("X-Super-Properties", _discordClient.Config.SuperProperties.Base64); var response = client.SendAsync(new HttpRequestMessage() { Content = hasData ? new System.Net.Http.StringContent(json, Encoding.UTF8, "application/json") : null, Method = new System.Net.Http.HttpMethod(method.ToString()), RequestUri = new Uri(endpoint) }).Result; resp = response.Content.ReadAsStringAsync().Result; statusCode = (int)response.StatusCode; } else { HttpRequest msg = new HttpRequest { IgnoreProtocolErrors = true, UserAgent = _discordClient.Config.UserAgent, Authorization = _discordClient.Token }; if (hasData) { msg.AddHeader(HttpHeader.ContentType, "application/json"); } if (Fingerprint != null) { msg.AddHeader("X-Fingerprint", Fingerprint); } msg.AddHeader("X-Super-Properties", _discordClient.Config.SuperProperties.Base64); if (_discordClient.Config.Proxy != null) { msg.Proxy = _discordClient.Config.Proxy; } var response = msg.Raw(method, endpoint, hasData ? new Leaf.xNet.StringContent(json) : null); resp = response.ToString(); statusCode = (int)response.StatusCode; } CheckResponse(resp, statusCode); return(new Response(resp)); } catch (RateLimitException ex) { if (_discordClient.Config.RetryOnRateLimit) { Thread.Sleep(ex.RetryAfter); } else { throw; } } } }
/// <summary> /// Sends an HTTP request and checks for errors /// </summary> /// <param name="method">HTTP method to use</param> /// <param name="endpoint">API endpoint (fx. /users/@me)</param> /// <param name="payload">JSON content</param> private async Task <DiscordHttpResponse> SendAsync(Leaf.xNet.HttpMethod method, string endpoint, object payload = null) { if (!endpoint.StartsWith("https")) { endpoint = DiscordHttpUtil.BuildBaseUrl(_discordClient.Config.ApiVersion, _discordClient.Config.SuperProperties.ReleaseChannel) + endpoint; } string json = "{}"; if (payload != null) { if (payload.GetType() == typeof(string)) { json = (string)payload; } else { json = JsonConvert.SerializeObject(payload); } } uint retriesLeft = _discordClient.Config.RestConnectionRetries; bool hasData = method == Leaf.xNet.HttpMethod.POST || method == Leaf.xNet.HttpMethod.PATCH || method == Leaf.xNet.HttpMethod.PUT || method == Leaf.xNet.HttpMethod.DELETE; while (true) { try { DiscordHttpResponse resp; if (_discordClient.Proxy == null || _discordClient.Proxy.Type == ProxyType.HTTP) { HttpClient client = new HttpClient(new HttpClientHandler() { Proxy = _discordClient.Proxy == null ? null : new WebProxy(_discordClient.Proxy.Host, _discordClient.Proxy.Port) }); if (_discordClient.Token != null) { client.DefaultRequestHeaders.Add("Authorization", _discordClient.Token); } if (_discordClient.User != null && _discordClient.User.Type == DiscordUserType.Bot) { client.DefaultRequestHeaders.Add("User-Agent", "Anarchy/0.8.1.0"); } else { client.DefaultRequestHeaders.Add("User-Agent", _discordClient.Config.SuperProperties.UserAgent); client.DefaultRequestHeaders.Add("X-Super-Properties", _discordClient.Config.SuperProperties.ToBase64()); } var response = await client.SendAsync(new HttpRequestMessage() { Content = hasData ? new System.Net.Http.StringContent(json, Encoding.UTF8, "application/json") : null, Method = new System.Net.Http.HttpMethod(method.ToString()), RequestUri = new Uri(endpoint) }); resp = new DiscordHttpResponse((int)response.StatusCode, response.Content.ReadAsStringAsync().Result); } else { HttpRequest msg = new HttpRequest { IgnoreProtocolErrors = true, UserAgent = _discordClient.User != null && _discordClient.User.Type == DiscordUserType.Bot ? "Anarchy/0.8.1.0" : _discordClient.Config.SuperProperties.UserAgent, Authorization = _discordClient.Token }; if (hasData) { msg.AddHeader(HttpHeader.ContentType, "application/json"); } if (_discordClient.User == null || _discordClient.User.Type == DiscordUserType.User) { msg.AddHeader("X-Super-Properties", _discordClient.Config.SuperProperties.ToBase64()); } if (_discordClient.Proxy != null) { msg.Proxy = _discordClient.Proxy; } var response = msg.Raw(method, endpoint, hasData ? new Leaf.xNet.StringContent(json) : null); resp = new DiscordHttpResponse((int)response.StatusCode, response.ToString()); } DiscordHttpUtil.ValidateResponse(resp.StatusCode, resp.Body); return(resp); } catch (Exception ex) when(ex is HttpException || ex is HttpRequestException || ex is TaskCanceledException) { if (retriesLeft == 0) { throw new DiscordConnectionException(); } retriesLeft--; } catch (RateLimitException ex) { if (_discordClient.Config.RetryOnRateLimit) { Thread.Sleep(ex.RetryAfter); } else { throw; } } } }