Skip to content

Commit

Permalink
feat: Support overriding default interceptors via request options
Browse files Browse the repository at this point in the history
  • Loading branch information
Ndiritu committed Nov 19, 2024
1 parent adf470a commit 667cae6
Show file tree
Hide file tree
Showing 2 changed files with 74 additions and 7 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import com.microsoft.graph.core.CoreConstants;
import com.microsoft.graph.core.requests.middleware.GraphTelemetryHandler;
import com.microsoft.graph.core.requests.options.GraphClientOption;
import com.microsoft.kiota.RequestOption;
import com.microsoft.kiota.authentication.BaseBearerTokenAuthenticationProvider;
import com.microsoft.kiota.http.KiotaClientFactory;
import com.microsoft.kiota.http.middleware.AuthorizationHandler;
Expand Down Expand Up @@ -58,8 +59,13 @@ public static OkHttpClient.Builder create(@Nonnull List<Interceptor> interceptor
*/
@Nonnull
public static OkHttpClient.Builder create(@Nonnull BaseBearerTokenAuthenticationProvider authenticationProvider) {
return create(authenticationProvider, new RequestOption[0]);
}

@Nonnull
public static OkHttpClient.Builder create(@Nonnull BaseBearerTokenAuthenticationProvider authenticationProvider, @Nonnull RequestOption[] requestOptions) {
final GraphClientOption graphClientOption = new GraphClientOption();
final Interceptor[] interceptors = createDefaultGraphInterceptors(graphClientOption);
final Interceptor[] interceptors = createDefaultGraphInterceptors(graphClientOption, requestOptions);
final ArrayList<Interceptor> interceptorList = new ArrayList<>(Arrays.asList(interceptors));
interceptorList.add(new AuthorizationHandler(authenticationProvider));
graphClientOption.featureTracker.setFeatureUsage(FeatureFlag.AUTH_HANDLER_FLAG);
Expand All @@ -75,7 +81,13 @@ public static OkHttpClient.Builder create(@Nonnull BaseBearerTokenAuthentication
*/
@Nonnull
public static OkHttpClient.Builder create(@Nonnull GraphClientOption graphClientOption, @Nonnull Interceptor... interceptors) {
return KiotaClientFactory.create(interceptors);
var builder = KiotaClientFactory.create(interceptors);
var customInterceptors = builder.interceptors();
var telemetryHandlerExists = customInterceptors.stream().anyMatch(x -> x instanceof GraphTelemetryHandler);
if (!telemetryHandlerExists) {
customInterceptors.add(new GraphTelemetryHandler(graphClientOption));
}
return builder;
}

/**
Expand All @@ -97,9 +109,15 @@ public static OkHttpClient.Builder create(@Nonnull GraphClientOption graphClient
*/
@Nonnull
public static OkHttpClient.Builder create(@Nullable GraphClientOption graphClientOption) {
return create(graphClientOption, new RequestOption[0]);
}

@Nonnull
public static OkHttpClient.Builder create(@Nullable GraphClientOption graphClientOption, @Nonnull RequestOption[] requestOptions) {
GraphClientOption options = graphClientOption != null ? graphClientOption : new GraphClientOption();
return KiotaClientFactory.create(createDefaultGraphInterceptors(options));
return KiotaClientFactory.create(createDefaultGraphInterceptors(options, requestOptions));
}

/**
* Creates the default Interceptors for use with Graph.
*
Expand All @@ -108,14 +126,31 @@ public static OkHttpClient.Builder create(@Nullable GraphClientOption graphClien
*/
@Nonnull
public static Interceptor[] createDefaultGraphInterceptors(@Nonnull GraphClientOption graphClientOption) {
List<Interceptor> handlers = new ArrayList<>();
addDefaultFeatureUsages(graphClientOption);
return createDefaultGraphInterceptors(graphClientOption, new RequestOption[0]);
}

@Nonnull
public static Interceptor[] createDefaultGraphInterceptors(@Nonnull GraphClientOption graphClientOption, @Nonnull RequestOption[] requestOptions) {
Objects.requireNonNull(requestOptions, "parameter requestOptions cannot be null");

UrlReplaceHandlerOption urlReplaceHandlerOption = new UrlReplaceHandlerOption(CoreConstants.ReplacementConstants.getDefaultReplacementPairs());

handlers.add(new UrlReplaceHandler(new UrlReplaceHandlerOption(CoreConstants.ReplacementConstants.getDefaultReplacementPairs())));
for (RequestOption option : requestOptions) {
if (option instanceof UrlReplaceHandlerOption) {
urlReplaceHandlerOption = (UrlReplaceHandlerOption) option;
}
}

List<Interceptor> handlers = new ArrayList<>();
handlers.add(urlReplaceHandlerOption == null ?
new UrlReplaceHandler(new UrlReplaceHandlerOption(CoreConstants.ReplacementConstants.getDefaultReplacementPairs())) :
new UrlReplaceHandler(urlReplaceHandlerOption));
handlers.add(new GraphTelemetryHandler(graphClientOption));
handlers.addAll(Arrays.asList(KiotaClientFactory.createDefaultInterceptors()));
handlers.addAll(Arrays.asList(KiotaClientFactory.createDefaultInterceptors(requestOptions)));
addDefaultFeatureUsages(graphClientOption);
return handlers.toArray(new Interceptor[0]);
}

//These are the default features used by the Graph Client
private static void addDefaultFeatureUsages(GraphClientOption graphClientOption) {
graphClientOption.featureTracker.setFeatureUsage(FeatureFlag.RETRY_HANDLER_FLAG);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,18 @@

import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;

import org.jetbrains.annotations.NotNull;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;

import com.azure.core.http.policy.RetryOptions;
import com.microsoft.graph.core.CoreConstants;
import com.microsoft.graph.core.authentication.AzureIdentityAccessTokenProvider;
import com.microsoft.graph.core.authentication.AzureIdentityAuthenticationProvider;
import com.microsoft.graph.core.requests.middleware.GraphTelemetryHandler;
import com.microsoft.kiota.RequestOption;
import com.microsoft.kiota.authentication.AccessTokenProvider;
import com.microsoft.kiota.authentication.AllowedHostsValidator;
import com.microsoft.kiota.authentication.BaseBearerTokenAuthenticationProvider;
Expand Down Expand Up @@ -50,6 +53,35 @@ void testCreateWithAuthenticationProvider() throws IOException {
assertEquals("Bearer " + ACCESS_TOKEN_STRING, response.request().header("Authorization"));
}

@Test
void testCreateWithAuthenticationProviderAndCustomRequestOptions() throws IOException {
final BaseBearerTokenAuthenticationProvider mockAuthenticationProvider =
getMockAuthenticationProvider();
var requestOptions = new ArrayList<RequestOption>();
requestOptions.add(new RetryHandlerOption(null, 0, 0));
OkHttpClient graphClient = GraphClientFactory.create(mockAuthenticationProvider, requestOptions.toArray(new RequestOption[0])).addInterceptor(new MockResponseHandler()).build();

var interceptors = graphClient.interceptors();
for (Interceptor interceptor : interceptors) {
if (interceptor instanceof RetryHandler) {
RetryHandlerOption retryOptions = ((RetryHandler) interceptor).getRetryOptions();
Assertions.assertEquals(0, retryOptions.maxRetries());
Assertions.assertEquals(0, retryOptions.delay());
}
}

Request request = new Request.Builder().url("https://graph.microsoft.com/v1.0/me")
.addHeader("CustomHeader", "CustomValue").build();
Response response = graphClient.newCall(request).execute();

assertEquals(200, response.code());
assertNotNull(response.request());
assertTrue(response.request().headers().names().contains("Authorization"));
assertTrue(response.request().headers().names().contains("CustomHeader"));
assertEquals("Bearer " + ACCESS_TOKEN_STRING, response.request().header("Authorization"));
assertEquals("CustomValue", response.request().header("CustomHeader"));
}

@Test
void testCreateWithCustomInterceptorsOverwritesDefaults() throws IOException {

Expand Down

0 comments on commit 667cae6

Please sign in to comment.