/// <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); }