From b6853fb80a55e7e05688cafd669302f2c3ec4cb0 Mon Sep 17 00:00:00 2001 From: "Justin \"J.R.\" Hill" Date: Mon, 2 Oct 2023 18:02:53 -0700 Subject: [PATCH] refactor: (first draft) Introduce error/exception types and abstract HttpRequest attempts --- .../java/dev/openfga/sdk/api/OpenFgaApi.java | 433 ++++++++++-------- .../openfga/sdk/api/auth/OAuth2Client.java | 31 +- .../dev/openfga/sdk/api/client/ApiClient.java | 73 ++- .../sdk/errors/FgaApiAuthenticationError.java | 14 + .../sdk/errors/FgaApiInternalError.java | 14 + .../sdk/errors/FgaApiNotFoundError.java | 14 + .../errors/FgaApiRateLimitExceededError.java | 14 + .../sdk/errors/FgaApiValidationError.java | 14 + .../dev/openfga/sdk/api/OpenFgaApiTest.java | 2 +- .../sdk/api/auth/OAuth2ClientTest.java | 9 +- 10 files changed, 388 insertions(+), 230 deletions(-) create mode 100644 src/main/java/dev/openfga/sdk/errors/FgaApiAuthenticationError.java create mode 100644 src/main/java/dev/openfga/sdk/errors/FgaApiInternalError.java create mode 100644 src/main/java/dev/openfga/sdk/errors/FgaApiNotFoundError.java create mode 100644 src/main/java/dev/openfga/sdk/errors/FgaApiRateLimitExceededError.java create mode 100644 src/main/java/dev/openfga/sdk/errors/FgaApiValidationError.java diff --git a/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java b/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java index f5be21a..0072070 100644 --- a/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java +++ b/src/main/java/dev/openfga/sdk/api/OpenFgaApi.java @@ -13,7 +13,6 @@ package dev.openfga.sdk.api; import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.ObjectMapper; import dev.openfga.sdk.api.auth.*; import dev.openfga.sdk.api.client.*; import dev.openfga.sdk.api.configuration.*; @@ -40,9 +39,7 @@ import dev.openfga.sdk.errors.*; import dev.openfga.sdk.util.Pair; import java.io.IOException; -import java.io.InputStream; import java.net.URI; -import java.net.http.HttpClient; import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.time.Duration; @@ -50,7 +47,6 @@ import java.util.List; import java.util.StringJoiner; import java.util.concurrent.CompletableFuture; -import java.util.function.Consumer; /** * A low-level API representation of an OpenFGA server. @@ -58,28 +54,21 @@ * Most code should favor the simpler and higher-level {@link OpenFgaClient} when calling an OpenFGA server. */ public class OpenFgaApi { - private final HttpClient memberVarHttpClient; - private final ObjectMapper memberVarObjectMapper; private final Configuration configuration; + + private final ApiClient apiClient; private final OAuth2Client oAuth2Client; - private final Consumer memberVarInterceptor; - private final Consumer> memberVarResponseInterceptor; - private final Consumer> memberVarAsyncResponseInterceptor; public OpenFgaApi(Configuration configuration) throws FgaInvalidParameterException { this(configuration, new ApiClient()); } public OpenFgaApi(Configuration configuration, ApiClient apiClient) throws FgaInvalidParameterException { - memberVarHttpClient = apiClient.getHttpClient(); - memberVarObjectMapper = apiClient.getObjectMapper(); + this.apiClient = apiClient; this.configuration = configuration; - memberVarInterceptor = apiClient.getRequestInterceptor(); - memberVarResponseInterceptor = apiClient.getResponseInterceptor(); - memberVarAsyncResponseInterceptor = apiClient.getAsyncResponseInterceptor(); if (configuration.getCredentials().getCredentialsMethod() == CredentialsMethod.CLIENT_CREDENTIALS) { - this.oAuth2Client = new OAuth2Client(configuration, apiClient.getHttpClient(), apiClient.getObjectMapper()); + this.oAuth2Client = new OAuth2Client(configuration, apiClient); } else { this.oAuth2Client = null; } @@ -116,24 +105,9 @@ public CompletableFuture check( private CompletableFuture check(String storeId, CheckRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = checkRequestBuilder(storeId, body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("check", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = + checkRequestBuilder(storeId, body, configuration).build(); + return ApiClient.attemptHttpRequest(apiClient, "check", request, CheckResponse.class); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -172,11 +146,12 @@ private CompletableFuture> checkWithHttpInfo( throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = checkRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("check", localVarResponse)); @@ -188,8 +163,9 @@ private CompletableFuture> checkWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -228,7 +204,7 @@ private HttpRequest.Builder checkRequestBuilder(String storeId, CheckRequest bod } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -237,8 +213,8 @@ private HttpRequest.Builder checkRequestBuilder(String storeId, CheckRequest bod if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -272,24 +248,8 @@ public CompletableFuture createStore( private CompletableFuture createStore(CreateStoreRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { - HttpRequest.Builder localVarRequestBuilder = createStoreRequestBuilder(body, configuration); - return memberVarHttpClient - .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) - .thenComposeAsync(localVarResponse -> { - if (localVarResponse.statusCode() / 100 != 2) { - return CompletableFuture.failedFuture(new ApiException("createStore", localVarResponse)); - } - try { - String responseBody = localVarResponse.body(); - return CompletableFuture.completedFuture( - responseBody == null || responseBody.isBlank() - ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); - } catch (IOException e) { - return CompletableFuture.failedFuture(new ApiException(e)); - } - }); + HttpRequest request = createStoreRequestBuilder(body, configuration).build(); + return ApiClient.attemptHttpRequest(apiClient, "createStore", request, CreateStoreResponse.class); } catch (ApiException e) { return CompletableFuture.failedFuture(e); } @@ -325,11 +285,12 @@ private CompletableFuture> createStoreWithHttpI CreateStoreRequest body, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = createStoreRequestBuilder(body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("createStore", localVarResponse)); @@ -341,8 +302,11 @@ private CompletableFuture> createStoreWithHttpI localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -377,7 +341,7 @@ private HttpRequest.Builder createStoreRequestBuilder(CreateStoreRequest body, C } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -386,8 +350,8 @@ private HttpRequest.Builder createStoreRequestBuilder(CreateStoreRequest body, C if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -420,7 +384,8 @@ private CompletableFuture deleteStore(String storeId, Configuration config throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = deleteStoreRequestBuilder(storeId, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -463,11 +428,12 @@ private CompletableFuture> deleteStoreWithHttpInfo(String stor throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = deleteStoreRequestBuilder(storeId, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("deleteStore", localVarResponse)); @@ -510,8 +476,8 @@ private HttpRequest.Builder deleteStoreRequestBuilder(String storeId, Configurat if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -548,7 +514,8 @@ private CompletableFuture expand(String storeId, ExpandRequest b throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = expandRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -559,8 +526,9 @@ private CompletableFuture expand(String storeId, ExpandRequest b return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -603,11 +571,12 @@ private CompletableFuture> expandWithHttpInfo( throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = expandRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("expand", localVarResponse)); @@ -619,8 +588,9 @@ private CompletableFuture> expandWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -660,7 +630,7 @@ private HttpRequest.Builder expandRequestBuilder(String storeId, ExpandRequest b } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -669,8 +639,8 @@ private HttpRequest.Builder expandRequestBuilder(String storeId, ExpandRequest b if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -704,7 +674,8 @@ private CompletableFuture getStore(String storeId, Configurati throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = getStoreRequestBuilder(storeId, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -715,8 +686,9 @@ private CompletableFuture getStore(String storeId, Configurati return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -756,11 +728,12 @@ private CompletableFuture> getStoreWithHttpInfo( String storeId, Configuration configuration) throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = getStoreRequestBuilder(storeId, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("getStore", localVarResponse)); @@ -772,8 +745,10 @@ private CompletableFuture> getStoreWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -811,8 +786,8 @@ private HttpRequest.Builder getStoreRequestBuilder(String storeId, Configuration if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -850,7 +825,8 @@ private CompletableFuture listObjects( throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = listObjectsRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -861,8 +837,10 @@ private CompletableFuture listObjects( return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue( + responseBody, new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -905,11 +883,12 @@ private CompletableFuture> listObjectsWithHttpI throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = listObjectsRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("listObjects", localVarResponse)); @@ -921,8 +900,11 @@ private CompletableFuture> listObjectsWithHttpI localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -963,7 +945,7 @@ private HttpRequest.Builder listObjectsRequestBuilder( } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -972,8 +954,8 @@ private HttpRequest.Builder listObjectsRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1012,7 +994,8 @@ private CompletableFuture listStores( try { HttpRequest.Builder localVarRequestBuilder = listStoresRequestBuilder(pageSize, continuationToken, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -1023,8 +1006,10 @@ private CompletableFuture listStores( return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue( + responseBody, new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1068,11 +1053,12 @@ private CompletableFuture> listStoresWithHttpInf try { HttpRequest.Builder localVarRequestBuilder = listStoresRequestBuilder(pageSize, continuationToken, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("listStores", localVarResponse)); @@ -1084,8 +1070,10 @@ private CompletableFuture> listStoresWithHttpInf localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1138,8 +1126,8 @@ private HttpRequest.Builder listStoresRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1176,7 +1164,8 @@ private CompletableFuture read(String storeId, ReadRequest body, C throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = readRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -1187,8 +1176,9 @@ private CompletableFuture read(String storeId, ReadRequest body, C return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1231,11 +1221,12 @@ private CompletableFuture> readWithHttpInfo( throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = readRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("read", localVarResponse)); @@ -1247,8 +1238,9 @@ private CompletableFuture> readWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1287,7 +1279,7 @@ private HttpRequest.Builder readRequestBuilder(String storeId, ReadRequest body, } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -1296,8 +1288,8 @@ private HttpRequest.Builder readRequestBuilder(String storeId, ReadRequest body, if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1336,7 +1328,8 @@ private CompletableFuture readAssertions( try { HttpRequest.Builder localVarRequestBuilder = readAssertionsRequestBuilder(storeId, authorizationModelId, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -1347,8 +1340,11 @@ private CompletableFuture readAssertions( return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1393,11 +1389,12 @@ private CompletableFuture> readAssertionsWit try { HttpRequest.Builder localVarRequestBuilder = readAssertionsRequestBuilder(storeId, authorizationModelId, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("readAssertions", localVarResponse)); @@ -1409,8 +1406,11 @@ private CompletableFuture> readAssertionsWit localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1456,8 +1456,8 @@ private HttpRequest.Builder readAssertionsRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1495,7 +1495,8 @@ private CompletableFuture readAuthorizationModel try { HttpRequest.Builder localVarRequestBuilder = readAuthorizationModelRequestBuilder(storeId, id, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -1507,9 +1508,11 @@ private CompletableFuture readAuthorizationModel return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1552,11 +1555,12 @@ private CompletableFuture> readAutho try { HttpRequest.Builder localVarRequestBuilder = readAuthorizationModelRequestBuilder(storeId, id, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture( @@ -1569,9 +1573,11 @@ private CompletableFuture> readAutho localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1615,8 +1621,8 @@ private HttpRequest.Builder readAuthorizationModelRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1659,7 +1665,8 @@ private CompletableFuture readAuthorizationMode try { HttpRequest.Builder localVarRequestBuilder = readAuthorizationModelsRequestBuilder(storeId, pageSize, continuationToken, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -1671,9 +1678,11 @@ private CompletableFuture readAuthorizationMode return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1721,11 +1730,12 @@ private CompletableFuture> readAuth try { HttpRequest.Builder localVarRequestBuilder = readAuthorizationModelsRequestBuilder(storeId, pageSize, continuationToken, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture( @@ -1738,9 +1748,11 @@ private CompletableFuture> readAuth localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1799,8 +1811,8 @@ private HttpRequest.Builder readAuthorizationModelsRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -1849,7 +1861,8 @@ private CompletableFuture readChanges( try { HttpRequest.Builder localVarRequestBuilder = readChangesRequestBuilder(storeId, type, pageSize, continuationToken, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -1860,8 +1873,10 @@ private CompletableFuture readChanges( return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue( + responseBody, new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1915,11 +1930,12 @@ private CompletableFuture> readChangesWithHttpI try { HttpRequest.Builder localVarRequestBuilder = readChangesRequestBuilder(storeId, type, pageSize, continuationToken, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("readChanges", localVarResponse)); @@ -1931,8 +1947,11 @@ private CompletableFuture> readChangesWithHttpI localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -1992,8 +2011,8 @@ private HttpRequest.Builder readChangesRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -2030,7 +2049,8 @@ private CompletableFuture write(String storeId, WriteRequest body, Confi throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = writeRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -2041,8 +2061,9 @@ private CompletableFuture write(String storeId, WriteRequest body, Confi return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -2085,11 +2106,12 @@ private CompletableFuture> writeWithHttpInfo( throws ApiException, FgaInvalidParameterException { try { HttpRequest.Builder localVarRequestBuilder = writeRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture(new ApiException("write", localVarResponse)); @@ -2101,8 +2123,9 @@ private CompletableFuture> writeWithHttpInfo( localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue(responseBody, new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -2141,7 +2164,7 @@ private HttpRequest.Builder writeRequestBuilder(String storeId, WriteRequest bod } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -2150,8 +2173,8 @@ private HttpRequest.Builder writeRequestBuilder(String storeId, WriteRequest bod if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -2196,7 +2219,8 @@ private CompletableFuture writeAssertions( try { HttpRequest.Builder localVarRequestBuilder = writeAssertionsRequestBuilder(storeId, authorizationModelId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -2251,11 +2275,12 @@ private CompletableFuture> writeAssertionsWithHttpInfo( try { HttpRequest.Builder localVarRequestBuilder = writeAssertionsRequestBuilder(storeId, authorizationModelId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture( @@ -2308,7 +2333,7 @@ private HttpRequest.Builder writeAssertionsRequestBuilder( } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("PUT", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -2317,8 +2342,8 @@ private HttpRequest.Builder writeAssertionsRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } @@ -2357,7 +2382,8 @@ private CompletableFuture writeAuthorizationMod try { HttpRequest.Builder localVarRequestBuilder = writeAuthorizationModelRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { if (localVarResponse.statusCode() / 100 != 2) { @@ -2369,9 +2395,11 @@ private CompletableFuture writeAuthorizationMod return CompletableFuture.completedFuture( responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {})); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {})); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -2415,11 +2443,12 @@ private CompletableFuture> writeAut try { HttpRequest.Builder localVarRequestBuilder = writeAuthorizationModelRequestBuilder(storeId, body, configuration); - return memberVarHttpClient + return apiClient + .getHttpClient() .sendAsync(localVarRequestBuilder.build(), HttpResponse.BodyHandlers.ofString()) .thenComposeAsync(localVarResponse -> { - if (memberVarAsyncResponseInterceptor != null) { - memberVarAsyncResponseInterceptor.accept(localVarResponse); + if (apiClient.getAsyncResponseInterceptor() != null) { + apiClient.getAsyncResponseInterceptor().accept(localVarResponse); } if (localVarResponse.statusCode() / 100 != 2) { return CompletableFuture.failedFuture( @@ -2432,9 +2461,11 @@ private CompletableFuture> writeAut localVarResponse.headers().map(), responseBody == null || responseBody.isBlank() ? null - : memberVarObjectMapper.readValue( - responseBody, - new TypeReference() {}))); + : apiClient + .getObjectMapper() + .readValue( + responseBody, + new TypeReference() {}))); } catch (IOException e) { return CompletableFuture.failedFuture(new ApiException(e)); } @@ -2476,7 +2507,7 @@ private HttpRequest.Builder writeAuthorizationModelRequestBuilder( } try { - byte[] localVarPostBody = memberVarObjectMapper.writeValueAsBytes(body); + byte[] localVarPostBody = apiClient.getObjectMapper().writeValueAsBytes(body); localVarRequestBuilder.method("POST", HttpRequest.BodyPublishers.ofByteArray(localVarPostBody)); } catch (IOException e) { throw new ApiException(e); @@ -2485,8 +2516,8 @@ private HttpRequest.Builder writeAuthorizationModelRequestBuilder( if (readTimeout != null) { localVarRequestBuilder.timeout(readTimeout); } - if (memberVarInterceptor != null) { - memberVarInterceptor.accept(localVarRequestBuilder); + if (apiClient.getRequestInterceptor() != null) { + apiClient.getRequestInterceptor().accept(localVarRequestBuilder); } return localVarRequestBuilder; } diff --git a/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java b/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java index 5c74533..a544c08 100644 --- a/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java +++ b/src/main/java/dev/openfga/sdk/api/auth/OAuth2Client.java @@ -12,23 +12,18 @@ package dev.openfga.sdk.api.auth; -import com.fasterxml.jackson.databind.ObjectMapper; import dev.openfga.sdk.api.client.ApiClient; import dev.openfga.sdk.api.configuration.*; import dev.openfga.sdk.errors.ApiException; import dev.openfga.sdk.errors.FgaInvalidParameterException; import java.io.IOException; -import java.net.HttpURLConnection; -import java.net.http.HttpClient; import java.net.http.HttpRequest; -import java.net.http.HttpResponse; import java.time.Instant; import java.util.concurrent.CompletableFuture; public class OAuth2Client { - private final HttpClient httpClient; + private final ApiClient apiClient; private final Credentials credentials; - private final ObjectMapper mapper; private final AccessToken token = new AccessToken(); private final CredentialsFlowRequest authRequest; private final String apiTokenIssuer; @@ -37,14 +32,11 @@ public class OAuth2Client { * Initializes a new instance of the {@link OAuth2Client} class * * @param configuration Configuration, including credentials, that can be used to retrieve an access tokens - * @param httpClient Http client */ - public OAuth2Client(Configuration configuration, HttpClient httpClient, ObjectMapper mapper) - throws FgaInvalidParameterException { + public OAuth2Client(Configuration configuration, ApiClient apiClient) throws FgaInvalidParameterException { this.credentials = configuration.getCredentials(); - this.httpClient = httpClient; - this.mapper = mapper; + this.apiClient = apiClient; this.apiTokenIssuer = credentials.getClientCredentials().getApiTokenIssuer(); this.authRequest = new CredentialsFlowRequest(); this.authRequest.setClientId(credentials.getClientCredentials().getClientId()); @@ -78,27 +70,14 @@ public CompletableFuture getAccessToken() throws FgaInvalidParameterExce private CompletableFuture exchangeToken() throws ApiException, FgaInvalidParameterException { try { - byte[] body = mapper.writeValueAsBytes(authRequest); + byte[] body = apiClient.getObjectMapper().writeValueAsBytes(authRequest); Configuration config = new Configuration().apiUrl("https://" + apiTokenIssuer); HttpRequest request = ApiClient.requestBuilder("POST", "/oauth/token", body, config) .build(); - return httpClient - .sendAsync(request, HttpResponse.BodyHandlers.ofString()) - .thenCompose(httpResponse -> { - if (httpResponse.statusCode() != HttpURLConnection.HTTP_OK) { - return CompletableFuture.failedFuture(new ApiException("exchangeToken", httpResponse)); - } - try { - CredentialsFlowResponse response = - mapper.readValue(httpResponse.body(), CredentialsFlowResponse.class); - return CompletableFuture.completedFuture(response); - } catch (Exception e) { - return CompletableFuture.failedFuture(e); - } - }); + return ApiClient.attemptHttpRequest(apiClient, "exchangeToken", request, CredentialsFlowResponse.class); } catch (IOException e) { throw new ApiException(e); } diff --git a/src/main/java/dev/openfga/sdk/api/client/ApiClient.java b/src/main/java/dev/openfga/sdk/api/client/ApiClient.java index 6901fae..85a4992 100644 --- a/src/main/java/dev/openfga/sdk/api/client/ApiClient.java +++ b/src/main/java/dev/openfga/sdk/api/client/ApiClient.java @@ -20,9 +20,11 @@ import com.fasterxml.jackson.databind.SerializationFeature; import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; import dev.openfga.sdk.api.configuration.Configuration; -import dev.openfga.sdk.errors.FgaInvalidParameterException; +import dev.openfga.sdk.errors.*; import dev.openfga.sdk.util.Pair; +import java.io.IOException; import java.io.InputStream; +import java.net.HttpURLConnection; import java.net.URI; import java.net.URLEncoder; import java.net.http.HttpClient; @@ -35,7 +37,9 @@ import java.util.Collections; import java.util.List; import java.util.StringJoiner; +import java.util.concurrent.CompletableFuture; import java.util.function.Consumer; +import java.util.function.Supplier; import java.util.stream.Collectors; import org.openapitools.jackson.nullable.JsonNullableModule; @@ -239,6 +243,73 @@ protected HttpClient.Builder createDefaultHttpClientBuilder() { return HttpClient.newBuilder(); } + // Static for testability reasons + public static CompletableFuture attemptHttpRequest( + ApiClient apiClient, String name, HttpRequest request, Class clazz) throws ApiException { + Supplier>> callOnce = + () -> apiClient.getHttpClient().sendAsync(request, HttpResponse.BodyHandlers.ofString()); + + return callOnce.get().thenCompose(response -> { + int status = response.statusCode(); + String responseBody = response.body(); + + try { + checkStatus(name, response); + } catch (FgaApiRateLimitExceededError | FgaApiInternalError e) { + // TODO handle retry + return CompletableFuture.failedFuture(e); + } catch (Exception e) { + return CompletableFuture.failedFuture(e); + } + + if (status != HttpURLConnection.HTTP_OK && status != HttpURLConnection.HTTP_CREATED) { + return CompletableFuture.failedFuture(new ApiException(name, response)); + } + + try { + T body = apiClient.getObjectMapper().readValue(responseBody, clazz); + return CompletableFuture.completedFuture(body); + } catch (IOException e) { + return CompletableFuture.failedFuture(new ApiException(e)); + } + }); + } + + private static void checkStatus(String name, HttpResponse response) + throws FgaApiValidationError, FgaApiAuthenticationError, FgaApiNotFoundError, FgaApiRateLimitExceededError, + FgaApiInternalError { + + int status = response.statusCode(); + String body = response.body(); + + switch (status) { + case HttpURLConnection.HTTP_BAD_REQUEST: + case 422: // HTTP 422 Unprocessable Entity + throw new FgaApiValidationError(name, status, response.headers(), body); + + case HttpURLConnection.HTTP_UNAUTHORIZED: + case HttpURLConnection.HTTP_FORBIDDEN: + throw new FgaApiAuthenticationError(name, status, response.headers(), body); + + case HttpURLConnection.HTTP_NOT_FOUND: + throw new FgaApiNotFoundError(name, status, response.headers(), body); + + case 429: // HTTP 429 Too Many Requests + throw new FgaApiRateLimitExceededError(name, status, response.headers(), body); + + case HttpURLConnection.HTTP_INTERNAL_ERROR: + throw new FgaApiInternalError(name, status, response.headers(), body); + } + } + + // public static CompletableFuture retryHttpRequest( + // String name, + // HttpClient httpClient, + // HttpRequest.Builder requestBuilder, + // Class clazz, + // ObjectMapper mapper) { + // } + /** * Set a custom {@link HttpClient.Builder} object to use when creating the * {@link HttpClient} that is used by the API client. diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiAuthenticationError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiAuthenticationError.java new file mode 100644 index 0000000..14a4b2d --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiAuthenticationError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiAuthenticationError extends ApiException { + public FgaApiAuthenticationError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiAuthenticationError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiInternalError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiInternalError.java new file mode 100644 index 0000000..2ccf52c --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiInternalError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiInternalError extends ApiException { + public FgaApiInternalError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiInternalError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiNotFoundError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiNotFoundError.java new file mode 100644 index 0000000..5c395c9 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiNotFoundError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiNotFoundError extends ApiException { + public FgaApiNotFoundError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiNotFoundError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiRateLimitExceededError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiRateLimitExceededError.java new file mode 100644 index 0000000..73454b6 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiRateLimitExceededError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiRateLimitExceededError extends ApiException { + public FgaApiRateLimitExceededError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiRateLimitExceededError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/main/java/dev/openfga/sdk/errors/FgaApiValidationError.java b/src/main/java/dev/openfga/sdk/errors/FgaApiValidationError.java new file mode 100644 index 0000000..b915ab7 --- /dev/null +++ b/src/main/java/dev/openfga/sdk/errors/FgaApiValidationError.java @@ -0,0 +1,14 @@ +package dev.openfga.sdk.errors; + +import java.net.http.HttpHeaders; + +public class FgaApiValidationError extends ApiException { + public FgaApiValidationError( + String message, Throwable throwable, int code, HttpHeaders responseHeaders, String responseBody) { + super(message, code, responseHeaders, responseBody); + } + + public FgaApiValidationError(String message, int code, HttpHeaders responseHeaders, String responseBody) { + this(message, (Throwable) null, code, responseHeaders, responseBody); + } +} diff --git a/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java b/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java index d47efb6..88ce02a 100644 --- a/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java +++ b/src/test/java/dev/openfga/sdk/api/OpenFgaApiTest.java @@ -207,7 +207,7 @@ public void createStore_400() throws Exception { // Then mockHttpClient.verify().post("https://localhost/stores").called(1); - ApiException exception = assertInstanceOf(ApiException.class, execException.getCause()); + FgaApiValidationError exception = assertInstanceOf(FgaApiValidationError.class, execException.getCause()); assertEquals(400, exception.getCode()); assertEquals( "{\"code\":\"validation_error\",\"message\":\"Generic validation error\"}", diff --git a/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java b/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java index 8819c66..1a6a847 100644 --- a/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java +++ b/src/test/java/dev/openfga/sdk/api/auth/OAuth2ClientTest.java @@ -2,9 +2,12 @@ import static org.hamcrest.Matchers.is; import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.fasterxml.jackson.databind.ObjectMapper; import com.pgssoft.httpclient.HttpClientMock; +import dev.openfga.sdk.api.client.ApiClient; import dev.openfga.sdk.api.configuration.*; import dev.openfga.sdk.errors.FgaInvalidParameterException; import org.junit.jupiter.api.BeforeEach; @@ -36,7 +39,11 @@ public void setup() throws FgaInvalidParameterException { var configuration = new Configuration().apiUrl("").credentials(credentials); - oAuth2 = new OAuth2Client(configuration, mockHttpClient, mapper); + var apiClient = mock(ApiClient.class); + when(apiClient.getHttpClient()).thenReturn(mockHttpClient); + when(apiClient.getObjectMapper()).thenReturn(mapper); + + oAuth2 = new OAuth2Client(configuration, apiClient); } @Test