/// <summary> /// Request a generic resource from the service server(s). /// </summary> /// <param name="route"> /// The API route to make the request to. /// </param> /// <param name="responseReceived"> /// Gets set to false if no response was received, otherwise false. /// </param> /// <param name="noLogging"> /// Whether or not to log errors. Since HttpWebRequest brilliant throws exceptions for /// non-success HTTP status codes, it's nice to be able to control whether or not your /// request should have errors logged. /// </param> /// <returns> /// A non-null byte array on success. Null byte array on failure. /// </returns> public byte[] RequestResource(string resourceUri, out HttpStatusCode code, out bool responseReceived, ResourceOptions options = null, ServiceResource resource = ServiceResource.Custom) { if (options == null) { options = new ResourceOptions(); // Instantiate a resource options object with default options. } responseReceived = true; Dictionary <string, object> parameters = new Dictionary <string, object>(); try { // Try to send the device name as well. Helps distinguish between clients under the // same account. string deviceName = string.Empty; try { deviceName = Environment.MachineName; } catch { deviceName = "Unknown"; } var accessToken = WebServiceUtil.Default.AuthToken; //m_logger.Info("RequestResource1: accessToken=" + accessToken); IVersionProvider versionProvider = PlatformTypes.New <IVersionProvider>(); string version = versionProvider.GetApplicationVersion().ToString(3); // Build out post data with username and identifier. parameters.Add("identifier", FingerprintService.Default.Value); parameters.Add("device_id", deviceName); string postString = null; //string postString = string.Format("&identifier={0}&device_id={1}", FingerprintService.Default.Value, Uri.EscapeDataString(deviceName)); if (options.Parameters != null) { foreach (var parameter in options.Parameters) { parameters.Add(parameter.Key, parameter.Value); } } if (resource == ServiceResource.UserDataSumCheck || resource == ServiceResource.UserConfigSumCheck) { m_logger.Info("Sending version {0} to server", version); parameters.Add("app_version", version); } switch (options.ContentType) { case "application/x-www-form-urlencoded": postString = string.Join("&", parameters.Select(kv => $"{kv.Key}={kv.Value}")); break; case "application/json": postString = Newtonsoft.Json.JsonConvert.SerializeObject(parameters); break; } if (options.Method == "GET" || options.Method == "DELETE") { resourceUri += "?" + postString; if (postString.Contains("app_version")) { m_logger.Info("Sending postString as {0}", resourceUri); } } var request = GetApiBaseRequest(resourceUri, options); m_logger.Debug("WebServiceUtil.Request {0}", request.RequestUri); if (StringExtensions.Valid(accessToken)) { request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken)); } else if (resource != ServiceResource.RetrieveToken) { m_logger.Info("RequestResource1: Authorization failed."); AuthTokenRejected?.Invoke(); code = HttpStatusCode.Unauthorized; return(null); } if (options.Method != "GET" && options.Method != "DELETE") { if (postString.Contains("app_version")) { m_logger.Info("Sending {0} to server as {1}", postString, options.Method); } var formData = System.Text.Encoding.UTF8.GetBytes(postString); request.ContentLength = formData.Length; using (var requestStream = request.GetRequestStream()) { requestStream.Write(formData, 0, formData.Length); requestStream.Close(); } } m_logger.Info("RequestResource: uri={0}", request.RequestUri); // Now that our login form data has been POST'ed, get a response. using (var response = (HttpWebResponse)request.GetResponse()) { // Get the response code as an int so we can range check it. var intCode = (int)response.StatusCode; code = (HttpStatusCode)intCode; try { // Check if response code is considered a success code. if (intCode >= 200 && intCode <= 299) { using (var memoryStream = new MemoryStream()) { response.GetResponseStream().CopyTo(memoryStream); // We do this just in case we get something like a 204. The idea here // is that if we return a non-null, the call was a success. var responseBody = memoryStream.ToArray(); if (responseBody == null || intCode == 204) { return(null); } return(responseBody); } } else { m_logger.Info("When requesting resource, got unexpected response code of {0}.", code); } } finally { response.Close(); request.Abort(); } } } catch (WebException e) { // KF - Set this to 0 for default. 0's a pretty good indicator of no internet. code = 0; try { using (WebResponse response = e.Response) { if (response == null) { responseReceived = false; } HttpWebResponse httpResponse = (HttpWebResponse)response; m_logger.Error("Error code: {0}", httpResponse.StatusCode); int intCode = (int)httpResponse.StatusCode; code = (HttpStatusCode)intCode; // Auth failure means re-log EXCEPT when requesting deactivation. if ((intCode == 401 || intCode == 403) && resource != ServiceResource.DeactivationRequest) { WebServiceUtil.Default.AuthToken = string.Empty; m_logger.Info("RequestResource2: Authorization failed."); AuthTokenRejected?.Invoke(); } else if (intCode > 399 && intCode <= 499 && resource != ServiceResource.DeactivationRequest) { m_logger.Info("Error occurred in RequestResource: {0}", intCode); } using (Stream data = response.GetResponseStream()) using (var reader = new StreamReader(data)) { string text = reader.ReadToEnd(); m_logger.Error(text); } } } catch { } if (!options.NoLogging) { m_logger.Error(e.Message); m_logger.Error(e.StackTrace); } } catch (Exception e) { // XXX TODO - Good default? code = HttpStatusCode.InternalServerError; if (!options.NoLogging) { while (e != null) { m_logger.Error(e.Message); m_logger.Error(e.StackTrace); e = e.InnerException; } } } return(null); }
/// <summary> /// Attempts to post the given form-encoded data to the service API. /// </summary> /// <param name="route"> /// The API route to make the request to. /// </param> /// <param name="formEncodedData"> /// The form encoded data to post. /// </param> /// <param name="noLogging"> /// Whether or not to log errors. Since HttpWebRequest brilliant throws exceptions for /// non-success HTTP status codes, it's nice to be able to control whether or not your /// request should have errors logged. /// </param> /// <returns> /// True if the web service gave a success response, false otherwise. /// </returns> public bool SendResource(ServiceResource resource, byte[] formEncodedData, out HttpStatusCode code, bool noLogging = true) { try { // Try to send the device name as well. Helps distinguish between clients under the // same account. string deviceName = string.Empty; try { deviceName = Environment.MachineName; } catch { deviceName = "Unknown"; } var request = GetApiBaseRequest(m_namedResourceMap[resource], new ResourceOptions()); var accessToken = WebServiceUtil.Default.AuthToken; if (StringExtensions.Valid(accessToken)) { request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken)); } else { m_logger.Info("SendResource1: Authorization failed."); AuthTokenRejected?.Invoke(); code = HttpStatusCode.Unauthorized; return(false); } // Build out post data with username and identifier. var formData = System.Text.Encoding.UTF8.GetBytes(string.Format("identifier={0}&device_id={1}&", FingerprintService.Default.Value, Uri.EscapeDataString(deviceName))); // Merge all data. var finalData = new byte[formData.Length + formEncodedData.Length]; Array.Copy(formData, finalData, formData.Length); Array.Copy(formEncodedData, 0, finalData, formData.Length, formEncodedData.Length); formData = finalData; // Don't forget to the set the content length to the total length of our form POST data! request.ContentLength = formData.Length; // Grab the request stream so we can POST our login form data to it. using (var requestStream = request.GetRequestStream()) { // Write and close. requestStream.Write(formData, 0, formData.Length); requestStream.Close(); } // Now that our login form data has been POST'ed, get a response. using (var response = (HttpWebResponse)request.GetResponse()) { // Get the response code as an int so we can range check it. var intCode = (int)response.StatusCode; code = (HttpStatusCode)intCode; try { // Check if response code is considered a success code. if (intCode >= 200 && intCode <= 299) { return(true); } } finally { response.Close(); request.Abort(); } } } catch (WebException e) { // XXX TODO - Good default? code = HttpStatusCode.InternalServerError; try { using (WebResponse response = e.Response) { HttpWebResponse httpResponse = (HttpWebResponse)response; m_logger.Error("Error code: {0}", httpResponse.StatusCode); int intCode = (int)httpResponse.StatusCode; if (intCode == 401 || intCode == 403) { WebServiceUtil.Default.AuthToken = string.Empty; m_logger.Info("SendResource2: Authorization failed."); AuthTokenRejected?.Invoke(); } else if (intCode > 399 && intCode < 499) { m_logger.Info("SendResource2: Failed with client code {0}", intCode); } using (Stream data = response.GetResponseStream()) using (var reader = new StreamReader(data)) { string text = reader.ReadToEnd(); m_logger.Error(text); } } } catch { } if (noLogging == false) { m_logger.Error(e.Message); m_logger.Error(e.StackTrace); } } catch (Exception e) { // XXX TODO - Good default? code = HttpStatusCode.InternalServerError; if (noLogging == false) { while (e != null) { m_logger.Error(e.Message); m_logger.Error(e.StackTrace); e = e.InnerException; } } } return(false); }
/// <summary> /// Request a generic resource from the service server(s). /// </summary> /// <param name="route"> /// The API route to make the request to. /// </param> /// <param name="responseReceived"> /// Gets set to false if no response was received, otherwise false. /// </param> /// <param name="noLogging"> /// Whether or not to log errors. Since HttpWebRequest brilliant throws exceptions for /// non-success HTTP status codes, it's nice to be able to control whether or not your /// request should have errors logged. /// </param> /// <returns> /// A non-null byte array on success. Null byte array on failure. /// </returns> public byte[] RequestResource(ServiceResource resource, out HttpStatusCode code, out bool responseReceived, Dictionary <string, string> parameters = null, bool noLogging = false) { responseReceived = true; try { // Try to send the device name as well. Helps distinguish between clients under the // same account. string deviceName = string.Empty; try { deviceName = Environment.MachineName; } catch { deviceName = "Unknown"; } var request = GetApiBaseRequest(m_namedResourceMap[resource]); var accessToken = AuthToken; //m_logger.Info("RequestResource1: accessToken=" + accessToken); m_logger.Info("RequestResource: accessToken length={0}", accessToken == null ? "(null)" : accessToken.Length.ToString()); m_logger.Info("RequestResource: {0}", resource.ToString()); if (StringExtensions.Valid(accessToken)) { request.Headers.Add("Authorization", string.Format("Bearer {0}", accessToken)); } else if (resource != ServiceResource.RetrieveToken) { m_logger.Info("RequestResource1: Authorization failed."); AuthTokenRejected?.Invoke(); code = HttpStatusCode.Unauthorized; return(null); } System.Reflection.Assembly assembly = System.Reflection.Assembly.GetExecutingAssembly(); string version = System.Reflection.AssemblyName.GetAssemblyName(assembly.Location).Version.ToString(); // Build out post data with username and identifier. string postString = string.Format("&identifier={0}&device_id={1}", FingerPrint.Value, Uri.EscapeDataString(deviceName)); if (parameters != null) { foreach (var parameter in parameters) { postString += $"&{parameter.Key}={parameter.Value}"; } } if (resource == ServiceResource.UserDataSumCheck) { postString += string.Format("&app_version={0}", version); } var formData = System.Text.Encoding.UTF8.GetBytes(postString); // Don't forget to the set the content length to the total length of our form POST data! request.ContentLength = formData.Length; // Grab the request stream so we can POST our login form data to it. using (var requestStream = request.GetRequestStream()) { // Write and close. requestStream.Write(formData, 0, formData.Length); requestStream.Close(); } // Now that our login form data has been POST'ed, get a response. using (var response = (HttpWebResponse)request.GetResponse()) { // Get the response code as an int so we can range check it. var intCode = (int)response.StatusCode; code = (HttpStatusCode)intCode; try { // Check if response code is considered a success code. if (intCode >= 200 && intCode <= 299) { using (var memoryStream = new MemoryStream()) { response.GetResponseStream().CopyTo(memoryStream); // We do this just in case we get something like a 204. The idea here // is that if we return a non-null, the call was a success. var responseBody = memoryStream.ToArray(); if (responseBody == null || intCode == 204) { return(null); } return(responseBody); } } else { m_logger.Info("When requesting resource, got unexpected response code of {0}.", code); } } finally { response.Close(); request.Abort(); } } } catch (WebException e) { // KF - Set this to 0 for default. 0's a pretty good indicator of no internet. code = 0; try { using (WebResponse response = e.Response) { if (response == null) { responseReceived = false; } HttpWebResponse httpResponse = (HttpWebResponse)response; m_logger.Error("Error code: {0}", httpResponse.StatusCode); int intCode = (int)httpResponse.StatusCode; code = (HttpStatusCode)intCode; // Auth failure means re-log EXCEPT when requesting deactivation. if ((intCode == 401 || intCode == 403) && resource != ServiceResource.DeactivationRequest) { AuthToken = string.Empty; m_logger.Info("RequestResource2: Authorization failed."); AuthTokenRejected?.Invoke(); } else if (intCode > 399 && intCode <= 499 && resource != ServiceResource.DeactivationRequest) { m_logger.Info("Error occurred in RequestResource: {0}", intCode); } using (Stream data = response.GetResponseStream()) using (var reader = new StreamReader(data)) { string text = reader.ReadToEnd(); m_logger.Error(text); } } } catch { } if (noLogging == false) { m_logger.Error(e.Message); m_logger.Error(e.StackTrace); } } catch (Exception e) { // XXX TODO - Good default? code = HttpStatusCode.InternalServerError; if (noLogging == false) { while (e != null) { m_logger.Error(e.Message); m_logger.Error(e.StackTrace); e = e.InnerException; } } } return(null); }