private static IEnumerator SendRequest(UnityWebRequest www, Action <string> callback, Action <ApiResponseException> errback) { yield return(www.SendWebRequest()); if (www.isNetworkError) { errback(new ApiResponseException(www.error)); } else if (www.isHttpError) { var decoded = www.downloadHandler.text.FromJson <Dictionary <string, object> >(); ApiResponseException e = new ApiResponseException(www.downloadHandler.text); if (decoded != null) { e = new ApiResponseException(www.responseCode, decoded["message"].ToString(), (int)decoded["code"]); if (decoded.ContainsKey("error")) { _instance.CopyResponseError(decoded["error"], e); } } errback(e); } else { callback?.Invoke(www.downloadHandler?.text); } }
public void And_Using_Message_And_InnerException_Ctor_Then_Sets_Message_From_Param( Exception innerException) { var exception = new ApiResponseException(System.Net.HttpStatusCode.MethodNotAllowed, "something went wrong", innerException); exception.Message.Should().Be($"HTTP status code did not indicate success: 405 MethodNotAllowed"); exception.InnerException.Should().Be(innerException); }
/// <inheritdoc cref="IHttpAdapter"/> public async Task <string> SendAsync(string method, Uri uri, IDictionary <string, string> headers, byte[] body, int timeout) { var request = new HttpRequestMessage { RequestUri = uri, Method = new HttpMethod(method), Headers = { Accept = { new MediaTypeWithQualityHeaderValue("application/json") } } }; foreach (var kv in headers) { request.Headers.Add(kv.Key, kv.Value); } if (body != null) { request.Content = new ByteArrayContent(body); } var timeoutToken = new CancellationTokenSource(); timeoutToken.CancelAfter(TimeSpan.FromSeconds(timeout)); Logger?.InfoFormat("Send: method='{0}', uri='{1}', body='{2}'", method, uri, body); var response = await _httpClient.SendAsync(request, timeoutToken.Token); var contents = await response.Content.ReadAsStringAsync(); response.Content?.Dispose(); Logger?.InfoFormat("Received: status={0}, contents='{1}'", response.StatusCode, contents); if (response.IsSuccessStatusCode) { return(contents); } var decoded = contents.FromJson <Dictionary <string, object> >(); string message = decoded.ContainsKey("message") ? decoded["message"].ToString() : string.Empty; int grpcCode = decoded.ContainsKey("code") ? (int)decoded["code"] : -1; var exception = new ApiResponseException((int)response.StatusCode, message, grpcCode); if (decoded.ContainsKey("error")) { this.CopyResponseError(decoded["error"], exception); } throw exception; }
public static ApiResponse <T> EnsureSuccessStatusCode <T>(this ApiResponse <T> response) { if (response == null) { throw new ArgumentNullException(nameof(response)); } if (!IsSuccessStatusCode(response.StatusCode)) { throw ApiResponseException.Create(response); } return(response); }
/// <summary> /// Executes are request and parses into the requested type T /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public virtual async Task <T> Execute <T>() where T : BaseResponse { // Create our requested, based on the various parameters we have for this call HttpRequestMessage request = BuildRequest(); // Debug - notify listeners that we are making this request _messageHub.APIRequestSent(_requestDetails); // Send to the API HttpResponseMessage response = await _client.SendAsync(request); // Debug - get the raw JSON out so we can debug var responseDetails = new ResponseDetails(); responseDetails.StatusCode = ((int)response.StatusCode) + " " + response.StatusCode; responseDetails.JSON = await response.Content.ReadAsStringAsync(); // If it's an error, we parse out exception and throw if (!response.IsSuccessStatusCode) { ApiResponseException exception; try { var errorResponse = responseDetails.JSON.FromJSON <ErrorResponse>(); exception = new ApiResponseException(response.StatusCode, response.ReasonPhrase, errorResponse); } catch { // If it's not JSON formatted, we just render a general message exception = new ApiResponseException(HttpStatusCode.BadRequest, "A big exception occurred", new ErrorResponse { Message = responseDetails.JSON }); } _messageHub.APIError(exception); // Friendlier message for our UI throw new UserException(exception.Message); } // Parse and return _messageHub.APIResponseReceived(responseDetails); var result = responseDetails.JSON.FromJSON <T>(); return(result); }
public async void RetryConfiguration_NonTransientError_Throws() { var adapterSchedule = new TransientAdapterResponseType[1] { TransientAdapterResponseType.NonTransientError, }; var adapter = new TransientExceptionHttpAdapter(adapterSchedule); var client = TestsUtil.FromSettingsFile(TestsUtil.DefaultSettingsPath, adapter); client.GlobalRetryConfiguration = new RetryConfiguration(baseDelayMs: 1, maxRetries: 3); ApiResponseException e = await Assert.ThrowsAsync <ApiResponseException>(async() => await client.AuthenticateCustomAsync("test_id")); }
/// <summary> /// Performs an in-place copy of data from Nakama's error response into /// the data dictionary of an <see cref="Nakama.ApiResponseException"/>. /// </summary> /// <param name="adapter">The adapter receiving the error response.</param> /// <param name="err"> The decoded error field from the server response.</param> /// <param name="e"> The exception whose data dictionary is being written to.</param> public static void CopyResponseError(this IHttpAdapter adapter, object err, ApiResponseException e) { var errString = err as string; var errDict = err as Dictionary <string, object>; if (errString != null) { e.Data["error"] = err; } else if (errDict != null) { foreach (KeyValuePair <string, object> keyVal in errDict) { e.Data[keyVal.Key] = keyVal.Value; } } }
/// <summary> /// Notifies listeners that the API threw the given error /// </summary> /// <param name="errorMessage"></param> public void APIError(ApiResponseException errorMessage) { Connection.Clients.Group(GetCurrentAPIRequestGroupName()).APIError(errorMessage, TransactionId, Description); }
/// <summary> /// Executes are request and parses into the requested type T /// </summary> /// <typeparam name="T"></typeparam> /// <returns></returns> public virtual async Task <T> Execute <T>() where T : BaseResponse { bool readyForProcessing = false; // Create our requested, based on the various parameters we have for this call HttpRequestMessage request = BuildRequest(); HttpResponseMessage response = null; ResponseDetails responseDetails = null; do { if (PushPayRateLimiter.Instance.ShouldStop) { // chase up the stack to make sure not swallowed throw new Exception("Max retry window exceeded."); } // Wait any currently scheduled delay await Task.Delay(PushPayRateLimiter.Instance.CurrentDelay); // Send to the API response = await _client.SendAsync(request); // Debug - get the raw JSON out so we can debug responseDetails = new ResponseDetails { StatusCode = ((int)response.StatusCode) + " " + response.StatusCode, JSON = await response.Content.ReadAsStringAsync() }; readyForProcessing = response.StatusCode != (HttpStatusCode)429; if (!readyForProcessing && response.Headers.Contains("retry-after")) { var retryHeader = response.Headers.GetValues("retry-after"); var retryWindow = int.Parse(retryHeader?.FirstOrDefault()); PushPayRateLimiter.Instance.AddDelay(retryWindow); } } while (!readyForProcessing); PushPayRateLimiter.Instance.ResetDelay(); // If it's an error, we parse out exception and throw if (!response.IsSuccessStatusCode) { ApiResponseException exception; try { var errorResponse = responseDetails.JSON.FromJSON <ErrorResponse>(); exception = new ApiResponseException(response.StatusCode, response.ReasonPhrase, errorResponse); } catch { // If it's not JSON formatted, we just render a general message exception = new ApiResponseException(HttpStatusCode.BadRequest, "An exception occurred", new ErrorResponse { Message = responseDetails.JSON }); } // Friendlier message for our UI throw new UserException(exception.Message); } var result = responseDetails.JSON.FromJSON <T>(); return(result); }
public void And_Using_Message_Ctor_Then_Sets_Message_From_Param() { var exception = new ApiResponseException(System.Net.HttpStatusCode.BadRequest, "something went wrong"); exception.Message.Should().Be($"HTTP status code did not indicate success: 400 BadRequest"); }
private void ConfigJwtAuthentication(IServiceCollection services) { var symmetricKey = Convert.FromBase64String(EncryptionUtil.ToBase64Encode("123456abcdefqwer")); services.AddAuthentication(x => { x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme; x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme; }) .AddJwtBearer(x => { x.RequireHttpsMetadata = false; x.TokenValidationParameters = new TokenValidationParameters { ValidateIssuerSigningKey = true, IssuerSigningKey = new SymmetricSecurityKey(symmetricKey), ValidateIssuer = false, ValidateAudience = false, ValidateLifetime = true, ClockSkew = TimeSpan.Zero }; x.Events = new JwtBearerEvents() { OnAuthenticationFailed = async context => { Console.WriteLine("ABCDDDDDDDDDDDDDDDDDDD"); var apiErrorMessage = new ApiErrorMessage(); var statusCode = HttpStatusCode.Unauthorized; if (context.Exception is SecurityTokenExpiredException) { apiErrorMessage.ErrorCode = (int)ErrorCodeEnum.ACCESS_TOKEN_IS_EXPIRED; apiErrorMessage.ErrorMessage = ErrorMessageConstant.ACCESS_TOKEN_IS_EXPIRED; } else { apiErrorMessage.ErrorCode = (int)ErrorCodeEnum.ACCESS_TOKEN_IS_INVALID; apiErrorMessage.ErrorMessage = ErrorMessageConstant.ACCESS_TOKEN_IS_INVALID; statusCode = (HttpStatusCode.Forbidden); } var apiResponseException = new ApiResponseException() { ErrorMessages = new List <ApiErrorMessage> { apiErrorMessage }, StatusCode = statusCode }; var apiResponse = new ApiSingleResponse <string>() { Data = null, Errors = apiResponseException.ErrorMessages }; context.Response.StatusCode = (int)statusCode; context.Response.ContentType = "application/json"; await context.Response.WriteAsync(JsonSerializer.Serialize(apiResponse, new JsonSerializerOptions { PropertyNamingPolicy = JsonNamingPolicy.CamelCase })); } }; }); }