Skip to content

Commit

Permalink
feat: add ability to pass customer defined okhttp client
Browse files Browse the repository at this point in the history
  • Loading branch information
gastonfournier committed Sep 20, 2024
1 parent 5e0519a commit 61e4bd3
Show file tree
Hide file tree
Showing 4 changed files with 47 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package io.getunleash.android

import io.getunleash.android.backup.LocalStorageConfig
import io.getunleash.android.data.DataStrategy
import okhttp3.OkHttpClient
import java.util.UUID

/**
Expand All @@ -11,6 +12,7 @@ import java.util.UUID
* @property appName: name of the underlying application. Will be used as default in the [io.getunleash.android.data.UnleashContext] call (Required).
* @property pollingStrategy How to poll for features. (Optional - Defaults to [io.getunleash.android.data.DataStrategy] with poll interval set to 60 seconds).
* @property metricsStrategy How to poll for metrics. (Optional - Defaults to [io.getunleash.android.data.DataStrategy] with poll interval set to 60 seconds).
* @property httpClient Custom http client to be used. (Optional - Use if you want to pass in custom SSL certificates).
*/
data class UnleashConfig(
val proxyUrl: String?,
Expand All @@ -24,7 +26,8 @@ data class UnleashConfig(
pauseOnBackground = true,
),
val delayedInitialization: Boolean = true,
val forceImpressionData: Boolean = false
val forceImpressionData: Boolean = false,
val httpClient: OkHttpClient? = null,
) {
companion object {
val instanceId: String = UUID.randomUUID().toString()
Expand Down Expand Up @@ -62,6 +65,7 @@ data class UnleashConfig(
.newBuilder(parent = this)
val localStorageConfig: LocalStorageConfig.Builder = LocalStorageConfig()
.newBuilder(parent = this)
var httpClient: OkHttpClient? = null
fun build(): UnleashConfig {
if ((proxyUrl == null || clientKey == null) && (pollingStrategy.enabled || metricsStrategy.enabled)) {
throw IllegalStateException("You must either set proxyUrl and clientKey or disable both polling and metrics.")
Expand All @@ -74,7 +78,8 @@ data class UnleashConfig(
metricsStrategy = metricsStrategy.build(),
delayedInitialization = delayedInitialization,
forceImpressionData = forceImpressionData,
localStorageConfig = localStorageConfig.build()
localStorageConfig = localStorageConfig.build(),
httpClient = httpClient
)
}

Expand All @@ -86,5 +91,9 @@ data class UnleashConfig(

fun forceImpressionData(forceImpressionData: Boolean) =
apply { this.forceImpressionData = forceImpressionData }

fun httpClient(httpClient: OkHttpClient) = apply {
this.httpClient = httpClient
}
}
}
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
package io.getunleash.android.data

import io.getunleash.android.UnleashConfig
import okhttp3.OkHttpClient

/**
* @property enabled Whether the strategy is enabled or not. (Optional - Defaults to true)
* @property interval How often to perform the operation in milliseconds. (Optional - Defaults to 60000)
* @property delay How long to wait before starting the operation in milliseconds. (Optional - Defaults to 0)
* @property pauseOnBackground Whether the operation should pause when the app is in background. (Optional - Defaults to true)
* @property httpReadTimeout How long to wait for HTTP reads in milliseconds. (Optional - Defaults to 5000)
* @property httpWriteTimeout How long to wait for HTTP writes in milliseconds. (Optional - Defaults to 5000)
* @property httpConnectionTimeout How long to wait for HTTP connection in milliseconds. (Optional - Defaults to 2000)
* @property httpCacheSize Disk space (in bytes) set aside for http cache. (Optional - Defaults to 10MB)
* @property httpCustomHeaders Enables users to override httpCustomHeaders. (Optional - Defaults to empty)
Expand All @@ -17,8 +19,9 @@ data class DataStrategy(
val interval: Long = 60000,
val delay: Long = 0,
val pauseOnBackground: Boolean = true,
val httpConnectionTimeout: Long = 2000,
val httpConnectionTimeout: Long = 5000,
val httpReadTimeout: Long = 5000,
val httpWriteTimeout: Long = 5000,
val httpCacheSize: Long = 1024 * 1024 * 10,
val httpCustomHeaders: Map<String, String> = emptyMap(),
) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,11 @@ class ClientBuilder(private val unleashConfig: UnleashConfig, private val androi
clientName: String,
strategy: DataStrategy
): OkHttpClient {
val builder = OkHttpClient.Builder()
// either use the provided client or create a new one
val clientBuilder = unleashConfig.httpClient?.newBuilder() ?: OkHttpClient.Builder()
val builder = clientBuilder
.readTimeout(strategy.httpReadTimeout, TimeUnit.MILLISECONDS)
.writeTimeout(strategy.httpWriteTimeout, TimeUnit.MILLISECONDS)
.connectTimeout(strategy.httpConnectionTimeout, TimeUnit.MILLISECONDS)
if (unleashConfig.localStorageConfig.enabled) {
builder.cache(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,17 @@ package io.getunleash.android.http
import android.content.Context
import io.getunleash.android.BaseTest
import io.getunleash.android.UnleashConfig
import okhttp3.OkHttpClient
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyLong
import org.mockito.ArgumentMatchers.eq
import org.mockito.Mockito.mock
import org.mockito.Mockito.spy
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import java.util.concurrent.TimeUnit
import kotlin.io.path.createTempDirectory

class ClientBuilderTest : BaseTest() {
Expand Down Expand Up @@ -38,4 +46,24 @@ class ClientBuilderTest : BaseTest() {

assertThat(client.cache).isNull()
}

@Test
fun `when http client is provided by customer we should use it`() {
val builder = spy(OkHttpClient.Builder())
val customHttpClient = mock(OkHttpClient::class.java)
`when`(customHttpClient.newBuilder()).thenReturn(builder)
val config =
UnleashConfig.newBuilder("my-app")
.proxyUrl("https://localhost:4242/proxy")
.httpClient(customHttpClient)
.localStorageConfig.enabled(false)
.clientKey("some-key").build()

val clientBuilder = ClientBuilder(config, mock(Context::class.java))
clientBuilder.build("clientName", config.pollingStrategy)

verify(builder).readTimeout(5000, TimeUnit.MILLISECONDS)
verify(builder).writeTimeout(5000, TimeUnit.MILLISECONDS)
verify(builder).connectTimeout(5000, TimeUnit.MILLISECONDS)
}
}

0 comments on commit 61e4bd3

Please sign in to comment.