Skip to content

Commit

Permalink
Remove Ktor dependency (#829)
Browse files Browse the repository at this point in the history
  • Loading branch information
MGaetan89 authored Dec 16, 2024
1 parent e01699c commit 9b1ebb0
Show file tree
Hide file tree
Showing 24 changed files with 279 additions and 202 deletions.
1 change: 0 additions & 1 deletion .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,3 @@ updates:
- dependency-name: "com.comscore:*"
- dependency-name: "com.google.guava:*" # Guava is updated together with AndroidX Media3
- dependency-name: "com.tagcommander.lib:*"
- dependency-name: "io.ktor:*" # We don't want to update to Ktor 3 yet
Original file line number Diff line number Diff line change
Expand Up @@ -101,12 +101,6 @@ class PillarboxAndroidLibraryPublishingPlugin : Plugin<Project> {
packageListUrl.set(URI("https://kotlinlang.org/api/kotlinx.serialization/package-list"))
}

// TODO Enable this once the following issue is fixed: https://github.com/Kotlin/dokka/issues/3889
// externalDocumentationLinks.register("ktor") {
// url.set(URI("https://api.ktor.io"))
// packageListUrl.set(URI("https://api.ktor.io/package-list"))
// }

// This is currently broken in Dokka for Android modules. See: https://github.com/Kotlin/dokka/issues/2876
sourceLink {
val version = VersionConfig().versionName(default = name)
Expand Down
10 changes: 2 additions & 8 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,9 @@ kotlinx-coroutines = "1.9.0"
kotlinx-datetime = "0.6.1"
kotlinx-kover = "0.8.3"
kotlinx-serialization = "1.7.3"
ktor = "2.3.13"
mockk = "1.13.13"
okhttp = "4.12.0"
okio = "3.9.1"
robolectric = "4.14.1"
srg-data-provider = "0.10.1"
tag-commander-core = "5.4.3"
Expand Down Expand Up @@ -78,13 +78,6 @@ kotlinx-datetime = { module = "org.jetbrains.kotlinx:kotlinx-datetime", version.
kotlinx-kover-gradle = { module = "org.jetbrains.kotlinx:kover-gradle-plugin", version.ref = "kotlinx-kover" }
kotlinx-serialization-core = { module = "org.jetbrains.kotlinx:kotlinx-serialization-core", version.ref = "kotlinx-serialization" }
kotlinx-serialization-json = { module = "org.jetbrains.kotlinx:kotlinx-serialization-json", version.ref = "kotlinx-serialization" }
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
ktor-http = { module = "io.ktor:ktor-http", version.ref = "ktor" }
ktor-serialization = { module = "io.ktor:ktor-serialization", version.ref = "ktor" }
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
ktor-utils = { module = "io.ktor:ktor-utils", version.ref = "ktor" }
robolectric = { module = "org.robolectric:robolectric", version.ref = "robolectric" }
robolectric-annotations = { module = "org.robolectric:annotations", version.ref = "robolectric" }
robolectric-shadows-framework = { module = "org.robolectric:shadows-framework", version.ref = "robolectric" }
Expand Down Expand Up @@ -115,6 +108,7 @@ androidx-media3-test-utils = { module = "androidx.media3:media3-test-utils", ver
androidx-media3-test-utils-robolectric = { module = "androidx.media3:media3-test-utils-robolectric", version.ref = "androidx-media3" }
okhttp = { group = "com.squareup.okhttp3", name = "okhttp", version.ref = "okhttp" }
okhttp-logging-interceptor = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" }
okio = { group = "com.squareup.okio", name = "okio", version.ref = "okio" }
tagcommander-core = { group = "com.tagcommander.lib", name = "core", version.ref = "tag-commander-core" }
tagcommander-serverside = { group = "com.tagcommander.lib", name = "ServerSide", version.ref = "tag-commander-server-side" }
comscore = { group = "com.comscore", name = "android-analytics", version.ref = "comscore" }
Expand Down
7 changes: 1 addition & 6 deletions pillarbox-core-business/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -34,12 +34,7 @@ dependencies {
api(libs.kotlinx.datetime)
api(libs.kotlinx.serialization.core)
implementation(libs.kotlinx.serialization.json)
api(libs.ktor.client.core)
implementation(libs.ktor.client.okhttp)
implementation(libs.ktor.http)
implementation(libs.ktor.serialization.kotlinx.json)
implementation(libs.ktor.utils)
implementation(libs.okhttp)
api(libs.okhttp)
api(libs.tagcommander.core)

testImplementation(project(":pillarbox-player-testutils"))
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import androidx.media3.datasource.DataSourceException
import ch.srgssr.pillarbox.core.business.exception.BlockReasonException
import ch.srgssr.pillarbox.core.business.exception.DataParsingException
import ch.srgssr.pillarbox.core.business.exception.ResourceNotFoundException
import ch.srgssr.pillarbox.player.network.HttpResultException
import java.io.IOException

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import androidx.media3.datasource.DataSource
import androidx.media3.datasource.DataSpec
import androidx.media3.datasource.DefaultHttpDataSource
import ch.srgssr.pillarbox.player.utils.DebugLogger
import kotlinx.coroutines.runBlocking

/**
* A [DataSource] that injects an Akamai token into URLs containing the query parameter `withToken=true`.
Expand All @@ -24,9 +23,7 @@ class AkamaiTokenDataSource private constructor(
if (hasNeedAkamaiToken(outputUri)) {
DebugLogger.debug("Akamai", "open ${dataSpec.uri}")
val cleanUri = removeTokenQueryParameter(outputUri)
outputUri = runBlocking {
tokenProvider.tokenizeUri(cleanUri)
}
outputUri = tokenProvider.tokenizeUri(cleanUri)
return dataSource.open(dataSpec.buildUpon().setUri(outputUri).build())
}
return dataSource.open(dataSpec)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,19 @@ package ch.srgssr.pillarbox.core.business.akamai

import android.net.Uri
import android.net.UrlQuerySanitizer
import ch.srgssr.pillarbox.player.network.PillarboxHttpClient
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.get
import io.ktor.client.request.parameter
import io.ktor.http.appendEncodedPathSegments
import ch.srgssr.pillarbox.player.network.PillarboxOkHttp
import ch.srgssr.pillarbox.player.network.RequestSender.send
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import okhttp3.OkHttpClient
import okhttp3.Request

/**
* The [AkamaiTokenProvider] is responsible for fetching an Akamai token from `TOKEN_SERVICE_URL` and appending it to URIs.
*
* @param httpClient The HTTP client used to make requests to the token service. Defaults to a [PillarboxHttpClient] instance.
* @param okHttpClient The OkHttp client used to make requests to the token service. Defaults to a [PillarboxOkHttp] instance.
*/
class AkamaiTokenProvider(private val httpClient: HttpClient = PillarboxHttpClient()) {
class AkamaiTokenProvider(private val okHttpClient: OkHttpClient = PillarboxOkHttp()) {

/**
* Requests and appends an Akamai token to the provided URI.
Expand All @@ -30,7 +28,7 @@ class AkamaiTokenProvider(private val httpClient: HttpClient = PillarboxHttpClie
* @param uri The URI to be tokenized.
* @return The tokenized [Uri] if successful, otherwise the original [uri].
*/
suspend fun tokenizeUri(uri: Uri): Uri {
fun tokenizeUri(uri: Uri): Uri {
val acl = getAcl(uri)
val token = acl?.let {
val tokenResult = getToken(it)
Expand All @@ -39,15 +37,12 @@ class AkamaiTokenProvider(private val httpClient: HttpClient = PillarboxHttpClie
return token?.let { appendTokenToUri(uri, it) } ?: uri
}

private suspend fun getToken(acl: String): Result<Token> {
return runCatching {
httpClient.get(TOKEN_SERVICE_URL) {
url {
appendEncodedPathSegments("akahd/token")
parameter("acl", acl)
}
}.body<TokenResponse>().token
}
private fun getToken(acl: String): Result<Token> {
return Request.Builder()
.url(TOKEN_SERVICE_URL.format(acl))
.build()
.send<TokenResponse>(okHttpClient)
.map { it.token }
}

/**
Expand Down Expand Up @@ -76,7 +71,7 @@ class AkamaiTokenProvider(private val httpClient: HttpClient = PillarboxHttpClie
internal data class TokenResponse(val token: Token)

internal companion object {
private const val TOKEN_SERVICE_URL = "https://tp.srgssr.ch/"
private const val TOKEN_SERVICE_URL = "https://tp.srgssr.ch/akahd/token?acl=%s"

internal fun getAcl(uri: Uri): String? {
val path = uri.path
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,8 @@
package ch.srgssr.pillarbox.core.business.integrationlayer

import ch.srgssr.pillarbox.core.business.integrationlayer.service.IlHost
import io.ktor.http.URLBuilder
import io.ktor.http.appendEncodedPathSegments
import java.net.URL
import java.net.URLEncoder

/**
* Service used to get a scaled image URL. This only works for SRG images.
Expand All @@ -21,14 +20,8 @@ internal class ImageScalingService(
fun getScaledImageUrl(
imageUrl: String,
): String {
return URLBuilder(baseUrl.toString())
.appendEncodedPathSegments("images/")
.apply {
parameters.append("imageUrl", imageUrl)
parameters.append("format", "webp")
parameters.append("width", "480")
}
.build()
.toString()
val encodedImageUrl = URLEncoder.encode(imageUrl, Charsets.UTF_8.name())

return "${baseUrl}images/?imageUrl=$encodedImageUrl&format=webp&width=480"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,25 +6,24 @@ package ch.srgssr.pillarbox.core.business.integrationlayer.service

import android.net.Uri
import ch.srgssr.pillarbox.core.business.integrationlayer.data.MediaComposition
import ch.srgssr.pillarbox.player.network.PillarboxHttpClient
import io.ktor.client.HttpClient
import io.ktor.client.call.body
import io.ktor.client.request.get
import java.net.URL
import ch.srgssr.pillarbox.player.network.PillarboxOkHttp
import ch.srgssr.pillarbox.player.network.RequestSender.send
import okhttp3.OkHttpClient
import okhttp3.Request

/**
* A service for fetching a [MediaComposition] over HTTP.
*
* @param httpClient The Ktor [HttpClient] instance used for making HTTP requests.
* @param okHttpClient The OkHttp client instance used for making HTTP requests.
*/
class HttpMediaCompositionService(
private val httpClient: HttpClient = PillarboxHttpClient(),
private val okHttpClient: OkHttpClient = PillarboxOkHttp(),
) : MediaCompositionService {

override suspend fun fetchMediaComposition(uri: Uri): Result<MediaComposition> {
return runCatching {
httpClient.get(URL(uri.toString()))
.body()
}
return Request.Builder()
.url(uri.toString())
.build()
.send(okHttpClient)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import androidx.media3.common.MimeTypes
import androidx.media3.datasource.DataSource.Factory
import androidx.media3.exoplayer.source.DefaultMediaSourceFactory
import androidx.media3.exoplayer.source.MergingMediaSource
import ch.srgssr.pillarbox.core.business.HttpResultException
import ch.srgssr.pillarbox.core.business.akamai.AkamaiTokenDataSource
import ch.srgssr.pillarbox.core.business.akamai.AkamaiTokenProvider
import ch.srgssr.pillarbox.core.business.exception.DataParsingException
Expand All @@ -32,10 +31,10 @@ import ch.srgssr.pillarbox.core.business.tracker.comscore.ComScoreTracker
import ch.srgssr.pillarbox.player.PillarboxDsl
import ch.srgssr.pillarbox.player.asset.Asset
import ch.srgssr.pillarbox.player.asset.AssetLoader
import ch.srgssr.pillarbox.player.network.HttpResultException
import ch.srgssr.pillarbox.player.tracker.FactoryData
import ch.srgssr.pillarbox.player.tracker.MediaItemTracker
import ch.srgssr.pillarbox.player.tracker.MutableMediaItemTrackerData
import io.ktor.client.plugins.ClientRequestException
import kotlinx.serialization.SerializationException
import java.io.IOException

Expand Down Expand Up @@ -121,17 +120,9 @@ class SRGAssetLoader internal constructor(
checkNotNull(mediaItem.localConfiguration)
val result = mediaCompositionService.fetchMediaComposition(mediaItem.localConfiguration!!.uri).getOrElse {
when (it) {
is ClientRequestException -> {
throw HttpResultException(it)
}

is SerializationException -> {
throw DataParsingException(it)
}

else -> {
throw IOException(it.message)
}
is HttpResultException -> throw it
is SerializationException -> throw DataParsingException(it)
else -> throw IOException(it.message)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ import ch.srgssr.pillarbox.player.PillarboxDsl
import ch.srgssr.pillarbox.player.network.PillarboxOkHttp
import ch.srgssr.pillarbox.player.tracker.MediaItemTracker
import ch.srgssr.pillarbox.player.tracker.MutableMediaItemTrackerData
import io.ktor.client.HttpClient
import kotlinx.coroutines.Dispatchers
import okhttp3.OkHttpClient

/**
* Configuration class for [SRGAssetLoader].
Expand Down Expand Up @@ -84,15 +84,15 @@ class SRGAssetLoaderConfig internal constructor(context: Context) {
}

/**
* Sets the HTTP client used by the [MediaCompositionService] and [AkamaiTokenProvider].
* Sets the OkHttp client used by the [MediaCompositionService] and [AkamaiTokenProvider].
*
* Note that this will override any existing [MediaCompositionService] set using [mediaCompositionService].
*
* @param httpClient The HTTP client.
* @param okHttpClient The OkHttp client.
*/
fun httpClient(httpClient: HttpClient) {
mediaCompositionService = HttpMediaCompositionService(httpClient)
akamaiTokenProvider = AkamaiTokenProvider(httpClient)
fun httpClient(okHttpClient: OkHttpClient) {
mediaCompositionService = HttpMediaCompositionService(okHttpClient)
akamaiTokenProvider = AkamaiTokenProvider(okHttpClient)
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import androidx.test.ext.junit.runners.AndroidJUnit4
import ch.srgssr.pillarbox.core.business.exception.BlockReasonException
import ch.srgssr.pillarbox.core.business.exception.DataParsingException
import ch.srgssr.pillarbox.core.business.exception.ResourceNotFoundException
import ch.srgssr.pillarbox.player.network.HttpResultException
import org.junit.runner.RunWith
import java.io.IOException
import kotlin.test.BeforeTest
Expand Down Expand Up @@ -60,7 +61,7 @@ class SRGErrorMessageProviderTest {

@Test
fun `getErrorMessage HttpResultException`() {
val exception = HttpResultException("HTTP request failed")
val exception = HttpResultException(503, "HTTP request failed")
val (errorCode, errorMessage) = errorMessageProvider.getErrorMessage(playbackException(exception))

assertEquals(0, errorCode)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ package ch.srgssr.pillarbox.core.business
import ch.srgssr.pillarbox.core.business.integrationlayer.data.BlockReason
import ch.srgssr.pillarbox.core.business.integrationlayer.data.Chapter
import ch.srgssr.pillarbox.core.business.integrationlayer.data.MediaComposition
import ch.srgssr.pillarbox.player.network.PillarboxHttpClient.jsonSerializer
import ch.srgssr.pillarbox.player.network.jsonSerializer
import kotlinx.serialization.SerializationException
import kotlin.test.Test
import kotlin.test.assertEquals
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import android.net.Uri
import ch.srgssr.pillarbox.core.business.integrationlayer.data.MediaComposition
import ch.srgssr.pillarbox.core.business.integrationlayer.service.HttpMediaCompositionService
import ch.srgssr.pillarbox.core.business.integrationlayer.service.MediaCompositionService
import ch.srgssr.pillarbox.player.network.PillarboxHttpClient
import ch.srgssr.pillarbox.player.network.jsonSerializer

internal class LocalMediaCompositionWithFallbackService(
context: Context,
Expand All @@ -19,7 +19,7 @@ internal class LocalMediaCompositionWithFallbackService(

init {
val json = context.assets.open("media-compositions.json").bufferedReader().use { it.readText() }
mediaCompositions = PillarboxHttpClient.jsonSerializer.decodeFromString(json)
mediaCompositions = jsonSerializer.decodeFromString(json)
}

override suspend fun fetchMediaComposition(uri: Uri): Result<MediaComposition> {
Expand Down
1 change: 0 additions & 1 deletion pillarbox-demo/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,6 @@ dependencies {
implementation(libs.kotlinx.coroutines.core)
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.serialization.core)
implementation(libs.ktor.client.okhttp)
implementation(libs.okhttp)
implementation(libs.srg.data)
implementation(libs.srg.dataprovider.retrofit)
Expand Down
8 changes: 1 addition & 7 deletions pillarbox-player/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -49,13 +49,6 @@ dependencies {
api(libs.kotlinx.coroutines.core)
api(libs.kotlinx.serialization.core)
implementation(libs.kotlinx.serialization.json)
implementation(libs.ktor.client.content.negotiation)
api(libs.ktor.client.core)
implementation(libs.ktor.client.okhttp)
implementation(libs.ktor.http)
implementation(libs.ktor.serialization)
implementation(libs.ktor.serialization.kotlinx.json)
implementation(libs.ktor.utils)
api(libs.okhttp)
implementation(libs.okhttp.logging.interceptor)

Expand All @@ -70,6 +63,7 @@ dependencies {
testImplementation(libs.kotlinx.coroutines.test)
testImplementation(libs.mockk)
testImplementation(libs.mockk.dsl)
testImplementation(libs.okio)
testRuntimeOnly(libs.robolectric)
testImplementation(libs.robolectric.annotations)
testImplementation(libs.robolectric.shadows.framework)
Expand Down
Loading

0 comments on commit 9b1ebb0

Please sign in to comment.