/// <exception cref="ApiException"></exception> private static async Task <HttpResponseMessage> SendCoreAsync(this HttpClient httpClient, HttpRequestMessage requestMessage, ApiRequest request) { try { return(await httpClient.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead).ConfigureAwait(false)); } catch (TaskCanceledException ex) when(ex.InnerException is TimeoutException) { // Handle timeout. throw ApiExceptions.ClientTimeout(request: request, innerException: ex); } catch (TaskCanceledException ex) when(ex.InnerException is SocketException) { throw ApiExceptions.ApiNotAvailable(request: request, innerException: ex); } catch (TaskCanceledException ex) { // Handle cancellation. throw ApiExceptions.RequestCanceled(request: request, innerException: ex); } //TODO: when using .net 5 //catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound) //{ // // Handle 404 // Console.WriteLine("Not found: " + ex.Message); //} catch (OperationCanceledException ex) { throw ApiExceptions.ApiNotAvailable(request, ex); } catch (Exception ex) { throw ApiExceptions.ClientUnkownError(request: request, innerException: ex); } }
public IObservable <Unit> IsAvailable() { return(Observable.Create <Unit>(async observer => { try { var endpoint = endpoints.Get; var request = new Request("", endpoint.Url, Enumerable.Empty <HttpHeader>(), endpoint.Method); var response = await apiClient.Send(request).ConfigureAwait(false); if (response.IsSuccess) { observer.OnNext(Unit.Default); } else { var error = ApiExceptions.For(request, response); observer.OnError(error); } } catch (Exception exception) { observer.OnError(exception); } observer.OnCompleted(); })); }
/// <exception cref="ApiException"></exception> protected static void EnsureApiNotReturnNull([ValidatedNotNull][NotNull] object?obj, string entityName) { if (obj == null) { throw ApiExceptions.ServerNullReturn(parameter: entityName); } }
/// <exception cref="ApiException"></exception> protected static void EnsureLogined() { if (!UserPreferences.IsLogined) { throw ApiExceptions.NoAuthority(); } }
private static async Task <string> makeRequest(string endpoint, HttpMethod method, IUser user, string json) { var requestMessage = AuthorizedRequestBuilder.CreateRequest( Credentials.WithApiToken(user.ApiToken), endpoint, method); if (json != null) { requestMessage.Content = new StringContent(json, Encoding.UTF8, "application/json"); } using (var client = new HttpClient()) { var response = await client.SendAsync(requestMessage); var data = await response.Content.ReadAsStringAsync(); if (response.IsSuccessStatusCode) { return(data); } throw ApiExceptions.For( new Request(json, requestMessage.RequestUri, new HttpHeader[0], requestMessage.Method), new Response(data, false, response.Content?.Headers?.ContentType?.MediaType, response.Headers, response.StatusCode)); } }
protected IObservable <T> CreateObservable <T>(Endpoint endpoint, IEnumerable <HttpHeader> headers, string body = "") { var request = new Request(body, endpoint.Url, headers, endpoint.Method); return(Observable.Create <T>(async observer => { var response = await apiClient.Send(request).ConfigureAwait(false); if (response.IsSuccess) { try { var data = !string.IsNullOrEmpty(response.RawData) ? await Task.Run(() => serializer.Deserialize <T>(response.RawData)).ConfigureAwait(false) : default(T); observer.OnNext(data); observer.OnCompleted(); } catch { observer.OnError(new DeserializationException <T>(response.RawData)); } } else { var exception = ApiExceptions.ForResponse(response); observer.OnError(exception); } })); }
public void ReturnsServerErrorException(HttpStatusCode httpStatusCode, Type expectedExceptionType) { var response = createErrorResponse(httpStatusCode); var exception = ApiExceptions.ForResponse(response); exception.Should().BeAssignableTo <ServerErrorException>().And.BeOfType(expectedExceptionType); }
public void ReturnsUnknownApiError(HttpStatusCode httpStatusCode) { var response = createErrorResponse(httpStatusCode); var exception = ApiExceptions.ForResponse(response); exception.Should().BeOfType <UnknownApiErrorException>() .Which.HttpCode.Should().Equals(httpStatusCode); }
public void ReturnsClientErrorException(HttpStatusCode httpStatusCode, Type expectedExceptionType) { var request = createRequest(HttpMethod.Get); var response = createErrorResponse(httpStatusCode); var exception = ApiExceptions.For(request, response); exception.Should().BeAssignableTo <ClientErrorException>().And.BeOfType(expectedExceptionType); }
public void CreatesAStringStartingWithExceptionName(HttpStatusCode statusCode, Type exceptionType) { var request = createRequest(HttpMethod.Get); var response = createErrorResponse(statusCode); var exception = ApiExceptions.For(request, response); var serialized = exception.ToString(); serialized.Should().StartWith($"{exceptionType.Name} "); }
public void ReturnsUnknownApiError(HttpStatusCode httpStatusCode) { var request = createRequest(HttpMethod.Get); var response = createErrorResponse(httpStatusCode); var exception = ApiExceptions.For(request, response); exception.Should().BeOfType <UnknownApiErrorException>() .Which.HttpCode.Should().Be(httpStatusCode); }
public virtual IEnumerable <TModel> GetAll(Func <DbSet <TModel>, IQueryable <TModel> > includes = null) { try { return(GetIncludes(includes)); } catch (Exception ex) { throw ApiExceptions.Error("Error while retrieving all objects", ex); } }
public async Task IsAvailable() { var endpoint = endpoints.Get; var request = new Request("", endpoint.Url, Enumerable.Empty <HttpHeader>(), endpoint.Method); var response = await apiClient.Send(request).ConfigureAwait(false); if (response.IsSuccess) { return; } throw ApiExceptions.For(request, response); }
public TResponse Login <TRequest, TResponse>(TRequest request) where TRequest : IJokJaBreIdentityRequest where TResponse : IJokJaBreIdentityResponse { var model = request.ToIdentityModel <TRequest, TIdentityModel>(m_configuration); var user = m_repository.Get(model); if (user == null) { throw ApiExceptions.NotFound("Username, email or password are not correct"); } return(user.ToIdentityResponse <TResponse>(m_configuration)); }
/// <exception cref="ApiException"></exception> protected static bool EnsureInternet(bool throwIfNot = true) { if (Connectivity.NetworkAccess != NetworkAccess.Internet) { if (throwIfNot) { throw ApiExceptions.NoInternet(cause: "没有联网,且不允许离线"); } return(false); } return(true); }
public TIdentityModel Create(TIdentityModel model) { try { var res = m_context.Set <TIdentityModel>().Add(model); m_context.SaveChanges(); res.Reload(); return(res.Entity); } catch (Exception ex) { throw ApiExceptions.Error("Error while creating identity object", ex); } }
private async Task <Exception> getExceptionFor(IRequest request, IResponse response, IEnumerable <HttpHeader> headers) { try { if (response.StatusCode == HttpStatusCode.Forbidden && await isLoggedIn(headers).ConfigureAwait(false) == false) { return(new UnauthorizedException(request, response)); } } catch (HttpRequestException) { return(new OfflineException()); } return(ApiExceptions.For(request, response)); }
public virtual async Task <bool> Delete <TClass>(TClass key) { try { var obj = m_context.Find <TModel>(key); if (obj == null) { throw ApiExceptions.ObjectNotFound; } m_context.Remove(obj); return((await m_context.SaveChangesAsync()) > 0); } catch (Exception ex) { throw ApiExceptions.Error("Error while deleting object", ex); } }
public async Task <TModel> Create(TModel model) { try { var res = await m_context.Set <TModel>().AddAsync(model); await m_context.SaveChangesAsync(); await res.ReloadAsync(); return(res.Entity); } catch (Exception ex) { throw ApiExceptions.Error("Error while creating object", ex); } }
/// <summary> /// ProcessFormFileAsync /// </summary> /// <param name="formFile"></param> /// <param name="permittedFileSuffixes"></param> /// <param name="sizeLimit"></param> /// <returns></returns> /// <exception cref="ApiException"></exception> public async Task <byte[]> ProcessFormFileAsync(IFormFile?formFile, string[] permittedFileSuffixes, long sizeLimit) { // Check the file length. This check doesn't catch files that only have // a BOM as their content. if (formFile == null || formFile.Length == 0 || permittedFileSuffixes.IsNullOrEmpty()) { throw ApiExceptions.ApiUploadEmptyFile(); } if (formFile.Length > sizeLimit) { throw ApiExceptions.ApiUploadOverSize(); } try { using MemoryStream memoryStream = new MemoryStream(); await formFile.CopyToAsync(memoryStream).ConfigureAwait(false); // Check the content length in case the file's only // content was a BOM and the content is actually // empty after removing the BOM. if (memoryStream.Length == 0) { throw ApiExceptions.ApiUploadEmptyFile(); } if (!IsValidFileExtensionAndSignature( formFile.FileName, memoryStream, permittedFileSuffixes)) { throw ApiExceptions.ApiUploadWrongType(); } else { return(memoryStream.ToArray()); } } catch (Exception ex) { throw ApiExceptions.ServerUnkownError(fileName: formFile.FileName, innerException: ex); } }
public virtual async Task <TModel> GetById <TClass>(TClass key, Func <DbSet <TModel>, IQueryable <TModel> > includes = null, bool shouldThrowIfNull = true) { TModel result; try { result = await((DbSet <TModel>)GetIncludes(includes)).FindAsync(key); } catch (Exception ex) { throw ApiExceptions.Error("Error while retrieving object", ex); } if (result == null && shouldThrowIfNull) { throw ApiExceptions.ObjectNotFound; } return(result); }
/// <exception cref="ApiException"></exception> public static async Task ThrowIfNotSuccessedAsync(HttpResponseMessage responseMessage) { if (responseMessage.IsSuccessStatusCode) { return; } //TODO: 可以处理404等ProblemDetails的返回 ErrorCode?errorCode = await responseMessage.DeSerializeJsonAsync <ErrorCode>().ConfigureAwait(false); responseMessage.Dispose(); if (errorCode == null) { throw ApiExceptions.ServerUnkownError(response: responseMessage); } else { throw ApiExceptions.ServerReturnError(errorCode); } }
public async Task <IResponse> Send(IRequest request) { var numberOfTries = 0; IResponse lastResponse = null; do { if (lastResponse != null) { wait(lastResponse); } lastResponse = await internalClient.Send(request); if (!shouldRetry(lastResponse.StatusCode)) { return(lastResponse); } }while (++numberOfTries < maximumNumberOfTries); Console.WriteLine($"Maximum number of retries ({maximumNumberOfTries}) exceeded."); throw ApiExceptions.For(request, lastResponse); }
/// <summary> /// RefreshAccessTokenAsync /// </summary> /// <param name="apiClient"></param> /// <param name="endpointSettings"></param> /// <returns></returns> /// <exception cref="ApiException"></exception> public static async Task <bool> RefreshAccessTokenAsync(IApiClient apiClient, EndpointSettings?endpointSettings) { if (UserPreferences.AccessToken.IsNullOrEmpty()) { return(false); } JwtEndpointSetting jwtEndpoint = endpointSettings == null?apiClient.GetDefaultJwtEndpointSetting() : endpointSettings.JwtEndpoint; string accessTokenHashKey = SecurityUtil.GetHash(UserPreferences.AccessToken); //这个AccessToken不久前刷新过 if (!_requestLimiter.NoWaitLock(nameof(RefreshAccessTokenAsync), accessTokenHashKey, TimeSpan.FromSeconds(jwtEndpoint.RefreshIntervalSeconds))) { //可能已经有人在刷新,等他刷新完 if (!await _lastRefreshResultsAccessSemaphore.WaitAsync(TimeSpan.FromSeconds(10)).ConfigureAwait(false)) { //等待失败 BaseApplication.ExceptionHandler(ApiExceptions.TokenRefreshError(cause: "AccessToken 有人刷新过,等待获取结果失败。")); return(false); } try { if (_lastRefreshResults.TryGetValue(accessTokenHashKey, out bool lastRefreshResult)) { return(lastRefreshResult); } BaseApplication.ExceptionHandler(ApiExceptions.TokenRefreshError(cause: "AccessToken 有人刷新过,但结果获取为空。")); return(false); } finally { _lastRefreshResultsAccessSemaphore.Release(); } } //开始刷新,其他想取结果的人等着 await _lastRefreshResultsAccessSemaphore.WaitAsync().ConfigureAwait(false); try { if (UserPreferences.RefreshToken.IsNotNullOrEmpty()) { RefreshAccessTokenRequest refreshRequest = new RefreshAccessTokenRequest( jwtEndpoint.EndpointName !, jwtEndpoint.Version !, HttpMethod.Get, jwtEndpoint.ResourceName !, UserPreferences.AccessToken, UserPreferences.RefreshToken); AccessTokenResource?resource = await apiClient.GetFirstOrDefaultAsync(refreshRequest).ConfigureAwait(false); if (resource != null) { _lastRefreshResults.Clear(); _lastRefreshResults[accessTokenHashKey] = true; OnRefreshSucceed(resource); return(true); } } //刷新失败 _lastRefreshResults.Clear(); _lastRefreshResults[accessTokenHashKey] = false; OnRefreshFailed(); return(false); } catch { //刷新失败 _lastRefreshResults.Clear(); _lastRefreshResults[accessTokenHashKey] = false; OnRefreshFailed(); throw; } finally { _lastRefreshResultsAccessSemaphore.Release(); } }