Skip to content

Commit fe0c468

Browse files
authored
feat(all): Add ability to use OkHttp4 with Amplify v2.x (#2970)
1 parent 97ddb8b commit fe0c468

File tree

17 files changed

+159
-30
lines changed

17 files changed

+159
-30
lines changed

aws-analytics-pinpoint/src/main/java/com/amplifyframework/analytics/pinpoint/PinpointManager.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ import com.amplifyframework.pinpoint.core.data.AndroidAppDetails
2424
import com.amplifyframework.pinpoint.core.data.AndroidDeviceDetails
2525
import com.amplifyframework.pinpoint.core.database.PinpointDatabase
2626
import com.amplifyframework.pinpoint.core.util.getUniqueId
27+
import com.amplifyframework.util.setHttpEngine
2728

2829
/**
2930
* PinpointManager is the entry point to Pinpoint Analytics and Targeting.
@@ -36,6 +37,7 @@ internal class PinpointManager constructor(
3637
val analyticsClient: AnalyticsClient
3738
val targetingClient: TargetingClient
3839
internal val pinpointClient: PinpointClient = PinpointClient {
40+
setHttpEngine()
3941
credentialsProvider = this@PinpointManager.credentialsProvider
4042
region = awsPinpointConfiguration.region
4143
}

aws-auth-cognito/src/main/java/com/amplifyframework/auth/cognito/AWSCognitoAuthService.kt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import aws.sdk.kotlin.services.cognitoidentityprovider.endpoints.CognitoIdentity
2222
import aws.smithy.kotlin.runtime.client.RequestInterceptorContext
2323
import aws.smithy.kotlin.runtime.client.endpoints.Endpoint
2424
import aws.smithy.kotlin.runtime.http.interceptors.HttpInterceptor
25+
import com.amplifyframework.util.setHttpEngine
2526

2627
interface AWSCognitoAuthService {
2728
val cognitoIdentityProviderClient: CognitoIdentityProviderClient?
@@ -33,6 +34,8 @@ interface AWSCognitoAuthService {
3334
val customPairs: MutableMap<String, String> = mutableMapOf()
3435
val cognitoIdentityProviderClient = configuration.userPool?.let { it ->
3536
CognitoIdentityProviderClient {
37+
setHttpEngine()
38+
3639
this.region = it.region
3740
this.endpointProvider = it.endpoint?.let { endpoint ->
3841
CognitoIdentityProviderEndpointProvider { Endpoint(endpoint) }
@@ -50,6 +53,8 @@ interface AWSCognitoAuthService {
5053

5154
val cognitoIdentityClient = configuration.identityPool?.let { it ->
5255
CognitoIdentityClient {
56+
setHttpEngine()
57+
5358
this.region = it.region
5459
this.interceptors += object : HttpInterceptor {
5560
override suspend fun modifyBeforeSerialization(context: RequestInterceptorContext<Any>): Any {

aws-auth-plugins-core/src/main/java/com/amplifyframework/auth/plugins/core/CognitoClientFactory.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,16 @@ import aws.smithy.kotlin.runtime.http.interceptors.HttpInterceptor
2222
import com.amplifyframework.auth.AWSCognitoAuthMetadataType
2323
import com.amplifyframework.auth.plugins.core.data.AWSCognitoIdentityPoolConfiguration
2424
import com.amplifyframework.plugins.core.BuildConfig
25+
import com.amplifyframework.util.setHttpEngine
2526

2627
internal object CognitoClientFactory {
2728
fun createIdentityClient(
2829
identityPool: AWSCognitoIdentityPoolConfiguration,
2930
pluginKey: String,
3031
pluginVersion: String,
3132
) = CognitoIdentityClient {
33+
setHttpEngine()
34+
3235
this.region = identityPool.region
3336
this.interceptors += object : HttpInterceptor {
3437
override suspend fun modifyBeforeSerialization(context: RequestInterceptorContext<Any>): Any {

aws-core/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ dependencies {
3535
implementation(libs.kotlin.stdlib)
3636
implementation(libs.kotlin.coroutines)
3737

38+
implementation(libs.aws.smithy.http)
39+
compileOnly(libs.aws.smithy.okhttp4)
40+
3841
implementation(libs.aws.credentials)
3942
// slf4j dependency is added to fix https://github.com/awslabs/aws-sdk-kotlin/issues/993#issuecomment-1678885524
4043
implementation(libs.slf4j)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/*
2+
* Copyright 2025 Amazon.com, Inc. or its affiliates. All Rights Reserved.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License").
5+
* You may not use this file except in compliance with the License.
6+
* A copy of the License is located at
7+
*
8+
* http://aws.amazon.com/apache2.0
9+
*
10+
* or in the "license" file accompanying this file. This file is distributed
11+
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
12+
* express or implied. See the License for the specific language governing
13+
* permissions and limitations under the License.
14+
*/
15+
16+
package com.amplifyframework.util
17+
18+
import aws.smithy.kotlin.runtime.http.config.HttpClientConfig
19+
import aws.smithy.kotlin.runtime.http.engine.okhttp4.OkHttp4Engine
20+
import com.amplifyframework.annotations.InternalAmplifyApi
21+
import com.amplifyframework.core.Amplify
22+
23+
internal object AmplifyHttp {
24+
25+
enum class Version {
26+
OkHttp4,
27+
OkHttp5
28+
}
29+
30+
private val logger = Amplify.Logging.logger("HttpEngine")
31+
32+
val availableVersion: Version by lazy {
33+
// Check to see if OkHttp4 Engine is available on the runtime classpath. If it is then the customer has
34+
// explicitly added it, so we can use that. Otherwise, use the OkHttp5 engine.
35+
try {
36+
Class.forName("aws.smithy.kotlin.runtime.http.engine.okhttp4.OkHttp4Engine")
37+
logger.info("Using OkHttp4 Engine")
38+
Version.OkHttp4
39+
} catch (e: ClassNotFoundException) {
40+
logger.info("Using default OkHttp5 Engine")
41+
Version.OkHttp5
42+
}
43+
}
44+
}
45+
46+
/**
47+
* This function is used to determine, at runtime, whether we should use the OkHttp4Engine instead of the
48+
* default OkHttp5Engine with Kotlin SDK. This allows customers that cannot use OkHttp5 (which is currently an alpha
49+
* release) to use OkHttp4 throughout Amplify by adding a dependency on aws.smithy.kotlin:http-client-engine-okhttp4
50+
* to their runtime classpath.
51+
* This must be called when instantiating any Client instance from the Kotlin SDK.
52+
*/
53+
@InternalAmplifyApi
54+
fun HttpClientConfig.Builder.setHttpEngine() {
55+
// The default engine is OkHttp5. If we should use OkHttp4 instead then override it here.
56+
if (AmplifyHttp.availableVersion == AmplifyHttp.Version.OkHttp4) {
57+
this.httpClient = OkHttp4Engine()
58+
}
59+
}

aws-geo-location/src/main/java/com/amplifyframework/geo/location/service/AmazonLocationService.kt

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,24 +26,20 @@ import com.amplifyframework.geo.models.Coordinates
2626
import com.amplifyframework.geo.models.CountryCode
2727
import com.amplifyframework.geo.models.Place
2828
import com.amplifyframework.geo.models.SearchArea
29+
import com.amplifyframework.util.setHttpEngine
2930

3031
/**
3132
* Implements the backend provider for the location plugin using
3233
* AWS Kotlin SDK's [LocationClient].
3334
* @param credentialsProvider AWS credentials provider for authorizing API calls
3435
* @param region AWS region for the Amazon Location Service
3536
*/
36-
internal class AmazonLocationService(
37-
credentialsProvider: CredentialsProvider,
38-
region: String
39-
) : GeoService<LocationClient> {
40-
override val provider: LocationClient
41-
42-
init {
43-
provider = LocationClient.invoke {
44-
this.credentialsProvider = credentialsProvider
45-
this.region = region
46-
}
37+
internal class AmazonLocationService(credentialsProvider: CredentialsProvider, region: String) :
38+
GeoService<LocationClient> {
39+
override val provider: LocationClient = LocationClient {
40+
setHttpEngine()
41+
this.credentialsProvider = credentialsProvider
42+
this.region = region
4743
}
4844

4945
override suspend fun getStyleJson(mapName: String): String {
@@ -75,17 +71,11 @@ internal class AmazonLocationService(
7571
val response = provider.searchPlaceIndexForText(request)
7672

7773
return response.results
78-
?.mapNotNull { it.place }
79-
?.map {
80-
AmazonLocationPlace(it)
81-
} ?: listOf()
74+
.mapNotNull { it.place }
75+
.map { AmazonLocationPlace(it) }
8276
}
8377

84-
override suspend fun reverseGeocode(
85-
index: String,
86-
position: Coordinates,
87-
limit: Int
88-
): List<Place> {
78+
override suspend fun reverseGeocode(index: String, position: Coordinates, limit: Int): List<Place> {
8979
val request = SearchPlaceIndexForPositionRequest.invoke {
9080
this.position = listOf(position.longitude, position.latitude)
9181
indexName = index
@@ -94,9 +84,7 @@ internal class AmazonLocationService(
9484
val response = provider.searchPlaceIndexForPosition(request)
9585

9686
return response.results
97-
?.mapNotNull { it.place }
98-
?.map {
99-
AmazonLocationPlace(it)
100-
} ?: listOf()
87+
.mapNotNull { it.place }
88+
.map { AmazonLocationPlace(it) }
10189
}
10290
}

aws-logging-cloudwatch/src/main/java/com/amplifyframework/logging/cloudwatch/AWSCloudWatchLoggingPlugin.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,9 @@ import com.amplifyframework.logging.LoggingPlugin
2828
import com.amplifyframework.logging.cloudwatch.models.AWSCloudWatchLoggingPluginConfiguration
2929
import com.amplifyframework.logging.cloudwatch.worker.CloudwatchRouterWorker
3030
import com.amplifyframework.logging.cloudwatch.worker.CloudwatchWorkerFactory
31+
import com.amplifyframework.util.setHttpEngine
3132
import java.net.URL
3233
import kotlinx.serialization.ExperimentalSerializationApi
33-
import kotlinx.serialization.decodeFromString
3434
import kotlinx.serialization.json.Json
3535
import org.json.JSONObject
3636

@@ -96,6 +96,7 @@ class AWSCloudWatchLoggingPlugin @JvmOverloads constructor(
9696
val awsLoggingConfig = awsCloudWatchLoggingPluginConfig ?: getConfigFromFile(pluginConfiguration)
9797
loggingConstraintsResolver.context = context
9898
cloudWatchLogsClient = CloudWatchLogsClient {
99+
setHttpEngine()
99100
credentialsProvider = CognitoCredentialsProvider()
100101
region = awsLoggingConfig.region
101102
}

aws-predictions/src/main/java/com/amplifyframework/predictions/aws/service/AWSComprehendService.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ import com.amplifyframework.predictions.models.Sentiment
4040
import com.amplifyframework.predictions.models.SentimentType
4141
import com.amplifyframework.predictions.models.Syntax
4242
import com.amplifyframework.predictions.result.InterpretResult
43-
import java.util.ArrayList
43+
import com.amplifyframework.util.setHttpEngine
4444
import java.util.concurrent.Executors
4545
import kotlinx.coroutines.runBlocking
4646

@@ -52,6 +52,7 @@ internal class AWSComprehendService(
5252
private val authCredentialsProvider: CredentialsProvider
5353
) {
5454
val client: ComprehendClient = ComprehendClient {
55+
setHttpEngine()
5556
this.region = pluginConfiguration.defaultRegion
5657
this.credentialsProvider = authCredentialsProvider
5758
}

aws-predictions/src/main/java/com/amplifyframework/predictions/aws/service/AWSPollyService.kt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import com.amplifyframework.predictions.PredictionsException
2727
import com.amplifyframework.predictions.aws.AWSPredictionsPluginConfiguration
2828
import com.amplifyframework.predictions.aws.models.AWSVoiceType
2929
import com.amplifyframework.predictions.result.TextToSpeechResult
30+
import com.amplifyframework.util.setHttpEngine
3031
import java.io.InputStream
3132
import java.util.concurrent.Executors
3233
import kotlinx.coroutines.runBlocking
@@ -40,6 +41,7 @@ internal class AWSPollyService(
4041
) {
4142
val client: PollyClient = AmazonPollyPresigningClient(
4243
PollyClient {
44+
setHttpEngine()
4345
this.region = pluginConfiguration.defaultRegion
4446
this.credentialsProvider = authCredentialsProvider
4547
}

aws-predictions/src/main/java/com/amplifyframework/predictions/aws/service/AWSRekognitionService.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ import com.amplifyframework.predictions.result.IdentifyEntityMatchesResult
4747
import com.amplifyframework.predictions.result.IdentifyLabelsResult
4848
import com.amplifyframework.predictions.result.IdentifyResult
4949
import com.amplifyframework.predictions.result.IdentifyTextResult
50-
import java.lang.StringBuilder
50+
import com.amplifyframework.util.setHttpEngine
5151
import java.net.MalformedURLException
5252
import java.net.URL
5353
import java.nio.ByteBuffer
@@ -64,6 +64,7 @@ internal class AWSRekognitionService(
6464
) {
6565

6666
val client: RekognitionClient = RekognitionClient {
67+
setHttpEngine()
6768
this.region = pluginConfiguration.defaultRegion
6869
this.credentialsProvider = authCredentialsProvider
6970
}

0 commit comments

Comments
 (0)