diff --git a/KiteConnect/Kite.cs b/KiteConnect/Kite.cs index 45cd4ca..ebd8acb 100644 --- a/KiteConnect/Kite.cs +++ b/KiteConnect/Kite.cs @@ -1,10 +1,12 @@ using System; using System.Collections.Generic; -using System.IO; using System.Linq; -using System.Net; using System.Collections; using System.Reflection; +using System.Net.Http; +using System.Text; +using System.Net.Mime; +using System.Net; namespace KiteConnect { @@ -21,12 +23,12 @@ public class Kite private string _apiKey; private string _accessToken; private bool _enableLogging; - private WebProxy _proxy; + private int _timeout; private Action _sessionHook; - //private Cache cache = new Cache(); + private HttpClient httpClient; private readonly Dictionary _routes = new Dictionary { @@ -98,7 +100,7 @@ public class Kite /// Time in milliseconds for which the API client will wait for a request to complete before it fails /// To set proxy for http request. Should be an object of WebProxy. /// Number of connections to server. Client will reuse the connections if they are alive. - public Kite(string APIKey, string AccessToken = null, string Root = null, bool Debug = false, int Timeout = 7000, WebProxy Proxy = null, int Pool = 2) + public Kite(string APIKey, string AccessToken = null, string Root = null, bool Debug = false, int Timeout = 7000, IWebProxy Proxy = null, int Pool = 2) { _accessToken = AccessToken; _apiKey = APIKey; @@ -106,7 +108,16 @@ public Kite(string APIKey, string AccessToken = null, string Root = null, bool D _enableLogging = Debug; _timeout = Timeout; - _proxy = Proxy; + + HttpClientHandler httpClientHandler = new HttpClientHandler() + { + Proxy = Proxy, + }; + httpClient = new(httpClientHandler) + { + BaseAddress = new Uri(_root), + Timeout = TimeSpan.FromMilliseconds(Timeout), + }; ServicePointManager.DefaultConnectionLimit = Pool; } @@ -166,7 +177,7 @@ public string GetLoginURL() /// User structure with tokens and profile data public User GenerateSession(string RequestToken, string AppSecret) { - string checksum = Utils.SHA256(_apiKey + RequestToken + AppSecret); + string checksum = Utils.SHA256Hash(_apiKey + RequestToken + AppSecret); var param = new Dictionary { @@ -220,7 +231,7 @@ public TokenSet RenewAccessToken(string RefreshToken, string AppSecret) { var param = new Dictionary(); - string checksum = Utils.SHA256(_apiKey + RefreshToken + AppSecret); + string checksum = Utils.SHA256Hash(_apiKey + RefreshToken + AppSecret); Utils.AddIfNotNull(param, "api_key", _apiKey); Utils.AddIfNotNull(param, "refresh_token", RefreshToken); @@ -1213,28 +1224,22 @@ private dynamic Delete(string Route, dynamic Params = null) /// Adds extra headers to request /// /// Request object to add headers - private void AddExtraHeaders(ref HttpWebRequest Req) + private void AddExtraHeaders(ref HttpRequestMessage Req) { - var KiteAssembly = System.Reflection.Assembly.GetAssembly(typeof(Kite)); + var KiteAssembly = Assembly.GetAssembly(typeof(Kite)); if (KiteAssembly != null) - Req.UserAgent = "KiteConnect.Net/" + KiteAssembly.GetName().Version; + { + Req.Headers.UserAgent.TryParseAdd("KiteConnect.Net/" + KiteAssembly.GetName().Version); + } Req.Headers.Add("X-Kite-Version", "3"); Req.Headers.Add("Authorization", "token " + _apiKey + ":" + _accessToken); - //if(Req.Method == "GET" && cache.IsCached(Req.RequestUri.AbsoluteUri)) - //{ - // Req.Headers.Add("If-None-Match: " + cache.GetETag(Req.RequestUri.AbsoluteUri)); - //} - - Req.Timeout = _timeout; - if (_proxy != null) Req.Proxy = _proxy; - if (_enableLogging) { - foreach (string header in Req.Headers.Keys) + foreach (var header in Req.Headers) { - Console.WriteLine("DEBUG: " + header + ": " + Req.Headers.GetValues(header)[0]); + Console.WriteLine("DEBUG: " + header.Key + ": " + String.Join(",", header.Value.ToArray())); } } } @@ -1268,7 +1273,7 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict } } - HttpWebRequest request; + HttpRequestMessage request = new(); if (Method == "POST" || Method == "PUT") { @@ -1284,17 +1289,13 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict else requestBody = String.Join("&", (Params as Dictionary).Select(x => Utils.BuildParam(x.Key, x.Value))); - request = (HttpWebRequest)WebRequest.Create(url); - request.AllowAutoRedirect = true; - request.Method = Method; - request.ContentType = json ? "application/json" : "application/x-www-form-urlencoded"; - request.ContentLength = requestBody.Length; - if (_enableLogging) Console.WriteLine("DEBUG: " + Method + " " + url + "\n" + requestBody); + request.RequestUri = new Uri(url); + request.Method = new HttpMethod(Method); AddExtraHeaders(ref request); - using (Stream webStream = request.GetRequestStream()) - using (StreamWriter requestWriter = new StreamWriter(webStream)) - requestWriter.Write(requestBody); + if (_enableLogging) Console.WriteLine("DEBUG: " + Method + " " + url + "\n" + requestBody); + + request.Content = new StringContent(requestBody, Encoding.UTF8, json ? "application/json" : "application/x-www-form-urlencoded"); } else { @@ -1315,75 +1316,57 @@ private dynamic Request(string Route, string Method, dynamic Params = null, Dict url += "?" + String.Join("&", allParams.Select(x => Utils.BuildParam(x.Key, x.Value))); } - request = (HttpWebRequest)WebRequest.Create(url); - request.AllowAutoRedirect = true; - request.Method = Method; + request.RequestUri = new Uri(url); + request.Method = new HttpMethod(Method); if (_enableLogging) Console.WriteLine("DEBUG: " + Method + " " + url); AddExtraHeaders(ref request); } - WebResponse webResponse; - try - { - webResponse = request.GetResponse(); - } - catch (WebException e) - { - if (e.Response is null) - throw e; + HttpResponseMessage response = httpClient.Send(request); + HttpStatusCode status = response.StatusCode; - webResponse = e.Response; - } + string responseBody = response.Content.ReadAsStringAsync().Result; + if (_enableLogging) Console.WriteLine("DEBUG: " + ((int)status) + " " + responseBody + "\n"); - using (Stream webStream = webResponse.GetResponseStream()) + if (response.Content.Headers.ContentType.MediaType == MediaTypeNames.Application.Json) { - using (StreamReader responseReader = new StreamReader(webStream)) - { - string response = responseReader.ReadToEnd(); - if (_enableLogging) Console.WriteLine("DEBUG: " + (int)((HttpWebResponse)webResponse).StatusCode + " " + response + "\n"); - - HttpStatusCode status = ((HttpWebResponse)webResponse).StatusCode; - - if (webResponse.ContentType == "application/json") - { - Dictionary responseDictionary = Utils.JsonDeserialize(response); + Dictionary responseDictionary = Utils.JsonDeserialize(responseBody); - if (status != HttpStatusCode.OK) - { - string errorType = "GeneralException"; - string message = ""; + if (status != HttpStatusCode.OK) + { + string errorType = "GeneralException"; + string message = ""; - if (responseDictionary.ContainsKey("error_type")) - errorType = responseDictionary["error_type"]; + if (responseDictionary.ContainsKey("error_type")) + errorType = responseDictionary["error_type"]; - if (responseDictionary.ContainsKey("message")) - message = responseDictionary["message"]; + if (responseDictionary.ContainsKey("message")) + message = responseDictionary["message"]; - switch (errorType) + switch (errorType) + { + case "GeneralException": throw new GeneralException(message, status); + case "TokenException": { - case "GeneralException": throw new GeneralException(message, status); - case "TokenException": - { - _sessionHook?.Invoke(); - throw new TokenException(message, status); - } - case "PermissionException": throw new PermissionException(message, status); - case "OrderException": throw new OrderException(message, status); - case "InputException": throw new InputException(message, status); - case "DataException": throw new DataException(message, status); - case "NetworkException": throw new NetworkException(message, status); - default: throw new GeneralException(message, status); + _sessionHook?.Invoke(); + throw new TokenException(message, status); } - } - - return responseDictionary; + case "PermissionException": throw new PermissionException(message, status); + case "OrderException": throw new OrderException(message, status); + case "InputException": throw new InputException(message, status); + case "DataException": throw new DataException(message, status); + case "NetworkException": throw new NetworkException(message, status); + default: throw new GeneralException(message, status); } - else if (webResponse.ContentType == "text/csv") - return Utils.ParseCSV(response); - else - throw new DataException("Unexpected content type " + webResponse.ContentType + " " + response); } + + return responseDictionary; } + else if (response.Content.Headers.ContentType.MediaType == "text/csv") + return Utils.ParseCSV(responseBody); + else + throw new DataException("Unexpected content type " + response.Content.Headers.ContentType.MediaType + " " + response); + } #endregion diff --git a/KiteConnect/Utils.cs b/KiteConnect/Utils.cs index 1a1b6c7..0ce0345 100644 --- a/KiteConnect/Utils.cs +++ b/KiteConnect/Utils.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections; using System.Collections.Generic; using System.Linq;