diff --git a/src/main/java/io/split/android/client/network/AuthenticatedRequest.java b/src/main/java/io/split/android/client/network/AuthenticatedRequest.java new file mode 100644 index 000000000..335478531 --- /dev/null +++ b/src/main/java/io/split/android/client/network/AuthenticatedRequest.java @@ -0,0 +1,23 @@ +package io.split.android.client.network; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; +import java.util.Map; + +interface AuthenticatedRequest { + + void setHeader(@NonNull String name, @NonNull String value); + + @Nullable + String getHeader(@NonNull String name); + + @Nullable + Map> getHeaders(); + + int getStatusCode(); + + @Nullable + String getRequestUrl(); +} diff --git a/src/main/java/io/split/android/client/network/Authenticator.java b/src/main/java/io/split/android/client/network/Authenticator.java new file mode 100644 index 000000000..c23a39994 --- /dev/null +++ b/src/main/java/io/split/android/client/network/Authenticator.java @@ -0,0 +1,9 @@ +package io.split.android.client.network; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +interface Authenticator> { + + @Nullable T authenticate(@NonNull T request); +} diff --git a/src/main/java/io/split/android/client/network/SplitAuthenticatedRequest.java b/src/main/java/io/split/android/client/network/SplitAuthenticatedRequest.java new file mode 100644 index 000000000..7e797da5d --- /dev/null +++ b/src/main/java/io/split/android/client/network/SplitAuthenticatedRequest.java @@ -0,0 +1,65 @@ +package io.split.android.client.network; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import java.util.List; +import java.util.Map; + +import okhttp3.Request; +import okhttp3.Response; + +public class SplitAuthenticatedRequest implements AuthenticatedRequest { + + private final int mStatusCode; + private Request mRequest; + + SplitAuthenticatedRequest(Response response) { + mStatusCode = response.code(); + mRequest = response.request(); + } + + @Override + public void setHeader(@NonNull String name, @NonNull String value) { + if (mRequest == null) { + return; + } + + mRequest = mRequest.newBuilder().header(name, value).build(); + } + + @Nullable + @Override + public String getHeader(@NonNull String name) { + if (mRequest == null) { + return null; + } + + return mRequest.header(name); + } + + @Nullable + @Override + public Map> getHeaders() { + if (mRequest == null) { + return null; + } + + return mRequest.headers().toMultimap(); + } + + @Override + public int getStatusCode() { + return mStatusCode; + } + + @Nullable + @Override + public String getRequestUrl() { + if (mRequest == null) { + return null; + } + + return mRequest.url().toString(); + } +} diff --git a/src/main/java/io/split/android/client/network/SplitAuthenticator.java b/src/main/java/io/split/android/client/network/SplitAuthenticator.java new file mode 100644 index 000000000..542ff42dc --- /dev/null +++ b/src/main/java/io/split/android/client/network/SplitAuthenticator.java @@ -0,0 +1,6 @@ +package io.split.android.client.network; + +/** @noinspection unused*/ +public abstract class SplitAuthenticator implements Authenticator { + +} diff --git a/src/test/java/io/split/android/client/network/SplitAuthenticatorTest.java b/src/test/java/io/split/android/client/network/SplitAuthenticatorTest.java new file mode 100644 index 000000000..54bcc4e99 --- /dev/null +++ b/src/test/java/io/split/android/client/network/SplitAuthenticatorTest.java @@ -0,0 +1,114 @@ +package io.split.android.client.network; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; + +import org.junit.Test; + +import java.util.Collections; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +public class SplitAuthenticatorTest { + + @Test + public void authenticatorModifiesHeaders() { + Authenticator> splitAuthenticator = new Authenticator>() { + @Override + public AuthenticatedRequest authenticate(@NonNull AuthenticatedRequest request) { + request.setHeader("new-header", "value"); + + return request; + } + }; + + AuthenticatedMockRequest request = new AuthenticatedMockRequest(new MockRequest()); + Map> initialHeaders = new HashMap<>(request.getHeaders()); + + splitAuthenticator.authenticate(request); + + Map> finalHeaders = new HashMap<>(request.getHeaders()); + + assertEquals(2, initialHeaders.size()); + assertTrue(initialHeaders.containsKey("header1")); + assertTrue(initialHeaders.containsKey("header2")); + assertEquals(Collections.singletonList("value1"), initialHeaders.get("header1")); + assertEquals(Collections.singletonList("value2"), initialHeaders.get("header2")); + assertEquals(3, finalHeaders.size()); + assertTrue(finalHeaders.containsKey("header1")); + assertTrue(finalHeaders.containsKey("header2")); + assertTrue(finalHeaders.containsKey("new-header")); + assertEquals(Collections.singletonList("value1"), finalHeaders.get("header1")); + assertEquals(Collections.singletonList("value2"), finalHeaders.get("header2")); + assertEquals(Collections.singletonList("value"), finalHeaders.get("new-header")); + } + + private static class AuthenticatedMockRequest implements AuthenticatedRequest { + + private final MockRequest mRequest; + + public AuthenticatedMockRequest(MockRequest request) { + mRequest = request; + } + + @Override + public void setHeader(@NonNull String name, @NonNull String value) { + mRequest.setHeader(name, value); + } + + @Override + public String getHeader(@NonNull String name) { + return mRequest.getHeader(name); + } + + @Nullable + @Override + public Map> getHeaders() { + return mRequest.getHeaders(); + } + + @Override + public int getStatusCode() { + return 0; + } + + @Override + public String getRequestUrl() { + return null; + } + } + + private static class MockRequest { + private final Map> mHeaders = new ConcurrentHashMap<>(); + + MockRequest() { + mHeaders.put("header1", Collections.singletonList("value1")); + mHeaders.put("header2", Collections.singletonList("value2")); + } + + public void setHeader(@NonNull String name, @NonNull String value) { + if (mHeaders.get(name) != null) { + mHeaders.get(name).add(value); + } else { + mHeaders.put(name, Collections.singletonList(value)); + } + } + + public String getHeader(@NonNull String name) { + if (mHeaders.get(name) != null && mHeaders.get(name).size() > 0) { + return mHeaders.get(name).get(0); + } + + return null; + } + + public Map> getHeaders() { + return mHeaders; + } + } +}