From 1eccd585623494cda186fa323ecb08dcaae7bf56 Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:09:06 -0700 Subject: [PATCH 1/7] UrlReplaceHandler in Kiota-Java --- .../http/middleware/UrlReplaceHandler.java | 100 ++++++++++++++++++ .../options/UrlReplaceHandlerOption.java | 81 ++++++++++++++ .../kiota/http/UrlReplaceHandlerTest.java | 59 +++++++++++ 3 files changed, 240 insertions(+) create mode 100644 components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java create mode 100644 components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/UrlReplaceHandlerOption.java create mode 100644 components/http/okHttp/src/test/java/com/microsoft/kiota/http/UrlReplaceHandlerTest.java diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java new file mode 100644 index 000000000..c07235cdf --- /dev/null +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java @@ -0,0 +1,100 @@ +package com.microsoft.kiota.http.middleware; + +import com.microsoft.kiota.http.middleware.options.UrlReplaceHandlerOption; +import io.opentelemetry.api.trace.Span; +import io.opentelemetry.context.Scope; +import okhttp3.Interceptor; +import okhttp3.Request; +import okhttp3.Response; + +import javax.annotation.Nonnull; +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.net.URLDecoder; +import java.util.Map; +import java.util.Objects; + +/** + * A middleware to replace the url with the specified replacement pairs. + */ +public class UrlReplaceHandler implements Interceptor { + + private UrlReplaceHandlerOption mUrlReplaceHandlerOption; + + /** + * Instantiate a GraphTelemetryHandler with default GraphClientOption. + */ + public UrlReplaceHandler(){ + this(new UrlReplaceHandlerOption()); + } + /** + * Instantiate a GraphTelemetryHandler with specified GraphClientOption + * @param urlReplaceHandlerOption the specified GraphClientOption for the GraphTelemetryHandler. + */ + public UrlReplaceHandler(@Nonnull UrlReplaceHandlerOption urlReplaceHandlerOption){ + Objects.requireNonNull(urlReplaceHandlerOption); + this.mUrlReplaceHandlerOption = new UrlReplaceHandlerOption(urlReplaceHandlerOption.getReplacementPairs(), urlReplaceHandlerOption.isEnabled()); + } + /** {@inheritDoc} */ + @Nonnull + @Override + public Response intercept(@Nonnull Chain chain) throws IOException { + Objects.requireNonNull(chain, "parameter chain cannot be null"); + Request request = Objects.requireNonNull(chain.request(), "request cannot be null"); + UrlReplaceHandlerOption replaceOption = request.tag(UrlReplaceHandlerOption.class); + replaceOption = replaceOption == null ? mUrlReplaceHandlerOption : replaceOption; + if(!replaceOption.isEnabled() || replaceOption.getReplacementPairs().isEmpty()) { + return chain.proceed(request); + } + + final Span span = ObservabilityHelper.getSpanForRequest(request, "UrlReplaceHandler_Intercept"); + Scope scope = null; + if (span != null) { + scope = span.makeCurrent(); + span.setAttribute("com.microsoft.kiota.handler.urlreplace.enable", true); + } + try{ + request = replaceRequestUrl(request, replaceOption.getReplacementPairs()); + } finally { + if (scope != null) { + scope.close(); + } + if (span != null) { + span.end(); + } + } + return chain.proceed(request); + } + /** + * Gets the GraphClientOption for the GraphTelemetryHandler. + * @return the GraphClientOption for the GraphTelemetryHandler. + */ + public UrlReplaceHandlerOption getUrlReplaceHandlerOption() { + return new UrlReplaceHandlerOption(mUrlReplaceHandlerOption.getReplacementPairs(), mUrlReplaceHandlerOption.isEnabled()); + } + /** + * Sets the GraphClientOption for the GraphTelemetryHandler. + * @param urlReplaceHandlerOption the GraphClientOption to set. + */ + public void setUrlReplaceHandlerOption(UrlReplaceHandlerOption urlReplaceHandlerOption) { + this.mUrlReplaceHandlerOption = new UrlReplaceHandlerOption(urlReplaceHandlerOption.getReplacementPairs(), urlReplaceHandlerOption.isEnabled()); + } + /** + * Replaces the url of the request using the replacement pairs provided. + * @param request the request to replace the url of. + * @param replacementPairs the replacement pairs to use. + * @return the request with the updated url. + * @throws UnsupportedEncodingException if the url encoding is not supported. + */ + @Nonnull + public static Request replaceRequestUrl(@Nonnull Request request, @Nonnull Map replacementPairs) throws UnsupportedEncodingException { + Request.Builder builder = request.newBuilder(); + //Decoding the url since Request.url is encoded by default. + String replacedUrl = URLDecoder.decode(request.url().toString(), "UTF-8");//Using decode(String,String) method to maintain source compatibility with Java 8 + for (Map.Entry entry : replacementPairs.entrySet()) { + replacedUrl = replacedUrl.replace(entry.getKey(), entry.getValue()); + } + builder.url(replacedUrl); + return builder.build(); + } +} diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/UrlReplaceHandlerOption.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/UrlReplaceHandlerOption.java new file mode 100644 index 000000000..7cb730c02 --- /dev/null +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/UrlReplaceHandlerOption.java @@ -0,0 +1,81 @@ +package com.microsoft.kiota.http.middleware.options; + +import com.microsoft.kiota.RequestOption; + +import javax.annotation.Nonnull; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** + * The options to be passed to the UrlReplaceHandler. + * Defines the replacement pairs and whether the handler is enabled or not. + */ +public class UrlReplaceHandlerOption implements RequestOption { + + private Map replacementPairs; + private boolean enabled; + + /** + * Instantiates a new UrlReplaceOption with an empty replacementPairs map and enabled set to true. + */ + public UrlReplaceHandlerOption() { + this(new HashMap<>()); + } + /** + * Instantiates a new UrlReplaceOption with the specified replacementPairs map and enabled set to true. + * @param replacementPairs the replacement pairs map. + */ + public UrlReplaceHandlerOption(@Nonnull Map replacementPairs) { + this(replacementPairs, true); + } + /** + * Instantiates a new UrlReplaceOption with the specified replacementPairs map and enabled set to the specified value. + * @param enabled whether the handler is enabled or not. + * @param replacementPairs the replacement pairs map. + */ + public UrlReplaceHandlerOption(@Nonnull Map replacementPairs, boolean enabled) { + Objects.requireNonNull(replacementPairs); + this.replacementPairs = new HashMap<>(replacementPairs); + this.enabled = enabled; + } + /** + * Gets the replacement pairs map. + * @return the replacement pairs map. + */ + public Map getReplacementPairs() { + return new HashMap<>(replacementPairs); + } + /** + * Sets the replacement pairs map. + * @param replacementPairs the replacement pairs map. + */ + public void setReplacementPairs(@Nonnull final Map replacementPairs) { + this.replacementPairs = new HashMap<>(replacementPairs); + } + /** + * Enables the handler. + */ + public void enable() { + this.enabled = true; + } + /** + * Disables the handler. + */ + public void disable() { + this.enabled = false; + } + /** + * Gets whether the handler is enabled or not. + * @return whether the handler is enabled or not. + */ + public boolean isEnabled() { + return enabled; + } + @Nonnull + @SuppressWarnings("unchecked") + @Override + public Class getType() { + return (Class) UrlReplaceHandlerOption.class; + } +} diff --git a/components/http/okHttp/src/test/java/com/microsoft/kiota/http/UrlReplaceHandlerTest.java b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/UrlReplaceHandlerTest.java new file mode 100644 index 000000000..80cae9c4b --- /dev/null +++ b/components/http/okHttp/src/test/java/com/microsoft/kiota/http/UrlReplaceHandlerTest.java @@ -0,0 +1,59 @@ +package com.microsoft.kiota.http; + +import com.microsoft.kiota.http.middleware.UrlReplaceHandler; +import com.microsoft.kiota.http.middleware.options.UrlReplaceHandlerOption; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import org.junit.jupiter.api.Test; + +import java.io.IOException; +import java.util.HashMap; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +class UrlReplaceHandlerTest { + + private final static String defaultUsersWithTokenUrl = "https://graph.microsoft.com/v1.0/users/TokenToReplace"; + private final static HashMap defaultReplacementPairs = new HashMap<>(); + + @Test + void testUrlReplaceHandler_no_replacementPairs() throws IOException { + Interceptor[] interceptors = new Interceptor[]{new UrlReplaceHandler(new UrlReplaceHandlerOption())}; + final OkHttpClient client = KiotaClientFactory.create(interceptors).build(); + final Request request = new Request.Builder().url(defaultUsersWithTokenUrl).build(); + final Response response = client.newCall(request).execute(); + + assertNotNull(response); + assertEquals(defaultUsersWithTokenUrl, response.request().url().toString()); //url should remain the same without replacement pairs + + } + @Test + void testUrlReplaceHandler_default_url() throws IOException { + defaultReplacementPairs.put("/users/TokenToReplace", "/me"); + Interceptor[] interceptors = new Interceptor[]{new UrlReplaceHandler(new UrlReplaceHandlerOption(defaultReplacementPairs))}; + final OkHttpClient client = KiotaClientFactory.create(interceptors).build(); + final Request request = new Request.Builder().url(defaultUsersWithTokenUrl).build(); + final Response response = client.newCall(request).execute(); + final String expectedNewUrl = "https://graph.microsoft.com/v1.0/me"; + + assertNotNull(response); + assertEquals(expectedNewUrl, response.request().url().toString()); + } + @Test + void testUrlReplaceHandler_multiple_pairs() throws IOException { + defaultReplacementPairs.put("/users/TokenToReplace", "/me"); + defaultReplacementPairs.put("{secondToken}", "expectedValue"); + String customUrl = "https://graph.microsoft.com/beta/users/TokenToReplace/{secondToken}"; //using special characters to test decoding. + Interceptor[] interceptors = new Interceptor[]{new UrlReplaceHandler(new UrlReplaceHandlerOption(defaultReplacementPairs))}; + final OkHttpClient client = KiotaClientFactory.create(interceptors).build(); + final Request request = new Request.Builder().url(customUrl).build(); + final Response response = client.newCall(request).execute(); + final String expectedNewUrl = "https://graph.microsoft.com/beta/me/expectedValue"; + + assertNotNull(response); + assertEquals(expectedNewUrl, response.request().url().toString()); + } +} \ No newline at end of file From 7cd0d77bbe1ae005f6bb4f4fca0a859546d09091 Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:11:25 -0700 Subject: [PATCH 2/7] UrlReplaceHandler in Kiota-Java --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8f1d88685..e6620e6a7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- Adds the 'UrlReplaceHandler' middleware to the Okhttp component to allow for customizing the URL before sending the request. + ## [0.4.6] - 2023-07-20 ### Added From 273d9fc7f0bedc43f900ad4214788c8c699723e9 Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Wed, 19 Jul 2023 15:12:06 -0700 Subject: [PATCH 3/7] changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6620e6a7..2852c1f41 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added -- Adds the 'UrlReplaceHandler' middleware to the Okhttp component to allow for customizing the URL before sending the request. +- Adds the `UrlReplaceHandler` middleware to the Okhttp component to allow for customizing the URL before sending the request. ## [0.4.6] - 2023-07-20 From cec3ff43a5dd3ac5c8aa6f34692f4357a0cae7a3 Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Thu, 20 Jul 2023 09:16:38 -0700 Subject: [PATCH 4/7] Update components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java Co-authored-by: Eastman --- .../com/microsoft/kiota/http/middleware/UrlReplaceHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java index c07235cdf..e75886359 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java @@ -28,7 +28,7 @@ public UrlReplaceHandler(){ this(new UrlReplaceHandlerOption()); } /** - * Instantiate a GraphTelemetryHandler with specified GraphClientOption + * Instantiate a UrlReplaceHandler with specified GraphClientOption * @param urlReplaceHandlerOption the specified GraphClientOption for the GraphTelemetryHandler. */ public UrlReplaceHandler(@Nonnull UrlReplaceHandlerOption urlReplaceHandlerOption){ From 5a42ba3fb449b16b8edcced317df3f2fa5d5278b Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Thu, 20 Jul 2023 09:31:40 -0700 Subject: [PATCH 5/7] Update UrlReplaceHandler.java javadoc corrections --- .../kiota/http/middleware/UrlReplaceHandler.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java index e75886359..4449f0020 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java @@ -22,14 +22,14 @@ public class UrlReplaceHandler implements Interceptor { private UrlReplaceHandlerOption mUrlReplaceHandlerOption; /** - * Instantiate a GraphTelemetryHandler with default GraphClientOption. + * Instantiate a UrlReplaceHandler with default UrlReplaceHandlerOption. */ public UrlReplaceHandler(){ this(new UrlReplaceHandlerOption()); } /** - * Instantiate a UrlReplaceHandler with specified GraphClientOption - * @param urlReplaceHandlerOption the specified GraphClientOption for the GraphTelemetryHandler. + * Instantiate a UrlReplaceHandler with specified UrlReplaceHandlerOption + * @param urlReplaceHandlerOption the specified UrlReplaceHandlerOption for the UrlReplaceHandler. */ public UrlReplaceHandler(@Nonnull UrlReplaceHandlerOption urlReplaceHandlerOption){ Objects.requireNonNull(urlReplaceHandlerOption); @@ -66,15 +66,15 @@ public Response intercept(@Nonnull Chain chain) throws IOException { return chain.proceed(request); } /** - * Gets the GraphClientOption for the GraphTelemetryHandler. - * @return the GraphClientOption for the GraphTelemetryHandler. + * Gets the UrlReplaceHandlerOption for the UrlReplaceHandler. + * @return the UrlReplaceHandlerOption for the UrlReplaceHandler. */ public UrlReplaceHandlerOption getUrlReplaceHandlerOption() { return new UrlReplaceHandlerOption(mUrlReplaceHandlerOption.getReplacementPairs(), mUrlReplaceHandlerOption.isEnabled()); } /** - * Sets the GraphClientOption for the GraphTelemetryHandler. - * @param urlReplaceHandlerOption the GraphClientOption to set. + * Sets the GraphClientOption for the UrlReplaceHandler. + * @param urlReplaceHandlerOption the UrlReplaceHandlerOption to set. */ public void setUrlReplaceHandlerOption(UrlReplaceHandlerOption urlReplaceHandlerOption) { this.mUrlReplaceHandlerOption = new UrlReplaceHandlerOption(urlReplaceHandlerOption.getReplacementPairs(), urlReplaceHandlerOption.isEnabled()); From 9c628f3ef04a5c4f0dd15e1b92dfc166c9813c72 Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Thu, 20 Jul 2023 10:39:29 -0700 Subject: [PATCH 6/7] Decoding url before replacement --- .../http/middleware/UrlReplaceHandler.java | 20 +++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java index c07235cdf..590c924b8 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java @@ -84,17 +84,21 @@ public void setUrlReplaceHandlerOption(UrlReplaceHandlerOption urlReplaceHandler * @param request the request to replace the url of. * @param replacementPairs the replacement pairs to use. * @return the request with the updated url. - * @throws UnsupportedEncodingException if the url encoding is not supported. */ @Nonnull - public static Request replaceRequestUrl(@Nonnull Request request, @Nonnull Map replacementPairs) throws UnsupportedEncodingException { + public static Request replaceRequestUrl(@Nonnull Request request, @Nonnull Map replacementPairs) { Request.Builder builder = request.newBuilder(); - //Decoding the url since Request.url is encoded by default. - String replacedUrl = URLDecoder.decode(request.url().toString(), "UTF-8");//Using decode(String,String) method to maintain source compatibility with Java 8 - for (Map.Entry entry : replacementPairs.entrySet()) { - replacedUrl = replacedUrl.replace(entry.getKey(), entry.getValue()); + try { + //Decoding the url since Request.url is encoded by default. + String replacedUrl = URLDecoder.decode(request.url().toString(), "UTF-8");//Using decode(String,String) method to maintain source compatibility with Java 8 + for (Map.Entry entry : replacementPairs.entrySet()) { + replacedUrl = replacedUrl.replace(entry.getKey(), entry.getValue()); + } + builder.url(replacedUrl); + return builder.build(); + + } catch (UnsupportedEncodingException e) { + return request; //This should never happen since "UTF-8" is a supported encoding. } - builder.url(replacedUrl); - return builder.build(); } } From db43ebfa8331deeebe7749b359a38464e4591a3a Mon Sep 17 00:00:00 2001 From: ramsessanchez <63934382+ramsessanchez@users.noreply.github.com> Date: Thu, 20 Jul 2023 10:41:31 -0700 Subject: [PATCH 7/7] Annotations and Changelog --- CHANGELOG.md | 4 ++++ .../microsoft/kiota/http/middleware/UrlReplaceHandler.java | 5 +++-- .../http/middleware/options/UrlReplaceHandlerOption.java | 1 + gradle.properties | 2 +- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 2852c1f41..be1672993 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +## [0.4.7] - 2023-07-21 + +### Added + - Adds the `UrlReplaceHandler` middleware to the Okhttp component to allow for customizing the URL before sending the request. ## [0.4.6] - 2023-07-20 diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java index 12163618c..5136ccb9f 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/UrlReplaceHandler.java @@ -69,14 +69,15 @@ public Response intercept(@Nonnull Chain chain) throws IOException { * Gets the UrlReplaceHandlerOption for the UrlReplaceHandler. * @return the UrlReplaceHandlerOption for the UrlReplaceHandler. */ + @Nonnull public UrlReplaceHandlerOption getUrlReplaceHandlerOption() { return new UrlReplaceHandlerOption(mUrlReplaceHandlerOption.getReplacementPairs(), mUrlReplaceHandlerOption.isEnabled()); } /** - * Sets the GraphClientOption for the UrlReplaceHandler. + * Sets the UrlReplaceHandlerOption for the UrlReplaceHandler. * @param urlReplaceHandlerOption the UrlReplaceHandlerOption to set. */ - public void setUrlReplaceHandlerOption(UrlReplaceHandlerOption urlReplaceHandlerOption) { + public void setUrlReplaceHandlerOption(@Nonnull UrlReplaceHandlerOption urlReplaceHandlerOption) { this.mUrlReplaceHandlerOption = new UrlReplaceHandlerOption(urlReplaceHandlerOption.getReplacementPairs(), urlReplaceHandlerOption.isEnabled()); } /** diff --git a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/UrlReplaceHandlerOption.java b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/UrlReplaceHandlerOption.java index 7cb730c02..0dc53b85c 100644 --- a/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/UrlReplaceHandlerOption.java +++ b/components/http/okHttp/src/main/java/com/microsoft/kiota/http/middleware/options/UrlReplaceHandlerOption.java @@ -43,6 +43,7 @@ public UrlReplaceHandlerOption(@Nonnull Map replacementPairs, bo * Gets the replacement pairs map. * @return the replacement pairs map. */ + @Nonnull public Map getReplacementPairs() { return new HashMap<>(replacementPairs); } diff --git a/gradle.properties b/gradle.properties index 66cc48b5f..6a1346055 100644 --- a/gradle.properties +++ b/gradle.properties @@ -26,7 +26,7 @@ org.gradle.caching=true mavenGroupId = com.microsoft.kiota mavenMajorVersion = 0 mavenMinorVersion = 4 -mavenPatchVersion = 6 +mavenPatchVersion = 7 mavenArtifactSuffix = #These values are used to run functional tests