Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use URLBuilder instead of Url in mappers and HttpFetcher #78

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
5e257bd
Use URLBuilder instead of Url in mappers and HttpFetcher
ayanyev Dec 4, 2023
6343169
kotlin 1.9.23 compose 1.6.1
luca992 Mar 14, 2024
0e77c53
fix tests, handle null content length as well
luca992 Mar 14, 2024
42f19b0
compose 1.6.1 fixes
luca992 Mar 14, 2024
c1a3b04
Merge branch 'compose-1.6'
luca992 Mar 14, 2024
dd3b6b1
Delete .github/workflows/refreshVersions.main.kts
luca992 Mar 14, 2024
90b798c
Delete .github/workflows/refreshVersions.yaml
luca992 Mar 14, 2024
6eb1dd7
Update README.md
luca992 Mar 31, 2024
0bc0efd
fix android sample
luca992 May 15, 2024
490d5b0
update dependencies
luca992 May 15, 2024
013f42e
update gradlew
luca992 May 15, 2024
a2ae058
kotlin 2.0
luca992 May 15, 2024
bcbbf8b
disable yarn use npm
luca992 May 16, 2024
22c9652
log gallery errors
luca992 May 16, 2024
9d4661a
use ktor 3.0 beta
luca992 May 16, 2024
b5bb34d
log gallery errors
luca992 May 16, 2024
669c789
fix resources path
luca992 May 20, 2024
9f90188
kotlin 2.0
luca992 May 22, 2024
2236c41
Merge branch 'kotlin-2.0'
luca992 May 25, 2024
256d13b
revert to ktor 2.3.11
luca992 May 25, 2024
6c838f8
npm lock
luca992 May 25, 2024
cc9069a
add test comment
luca992 May 25, 2024
5246d22
work around expect object kotlin 2.0 issue
luca992 May 25, 2024
96eaad8
v0.9.5
luca992 May 25, 2024
5caab5b
Merge branch 'main' into use-urlbuilder-instead-of-url-in-httpfetcher…
luca992 Jul 1, 2024
68a7737
Merge branch 'v1.0.0' into use-urlbuilder-instead-of-url-in-httpfetch…
luca992 Jul 1, 2024
6b2bb0e
merge fixes
luca992 Jul 1, 2024
b21fa8d
Make FileUrlFetcher a Fetcher<URLBuilder>
luca992 Jul 1, 2024
9ca1a9d
update code documentation
luca992 Jul 1, 2024
5baba60
remove testDefaultRequestWithUrl
luca992 Jul 1, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -337,7 +337,7 @@ The underlying disk cache is based on coil's multiplatform `DiskLruCache` implem

```kotlin
KamelConfig {
httpFetcher {
httpUrlFetcher {
// The size of the cache can be defined in bytes. Or DefaultHttpCacheSize (10 MiB) can be used.
httpCache(DefaultHttpCacheSize)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import kotlinx.coroutines.flow.Flow
import kotlin.reflect.KClass

/**
* Fetcher that fetches [ByteReadChannel] from the localhost using [Url].
* Fetcher that fetches [ByteReadChannel] from the localhost using [URLBuilder].
*/
internal actual val FileUrlFetcher = object : Fetcher<Url> {
override val inputDataKClass: KClass<Url> = Url::class
internal actual val FileUrlFetcher = object : Fetcher<URLBuilder> {
override val inputDataKClass: KClass<URLBuilder> = URLBuilder::class

override val source: DataSource = DataSource.Disk

override val Url.isSupported: Boolean
override val URLBuilder.isSupported: Boolean
get() = protocol.name == "file"

override fun fetch(data: Url, resourceConfig: ResourceConfig): Flow<Resource<ByteReadChannel>> {
override fun fetch(data: URLBuilder, resourceConfig: ResourceConfig): Flow<Resource<ByteReadChannel>> {
return FileFetcher.fetch(File(data.encodedPath), resourceConfig)
}
}
}
16 changes: 8 additions & 8 deletions kamel-core/src/appleMain/kotlin/io/kamel/core/mapper/Mappers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,21 +5,21 @@ import io.kamel.core.utils.URL
import io.ktor.http.*
import kotlin.reflect.KClass

internal actual val URLMapper: Mapper<URL, Url> = object : Mapper<URL, Url> {
internal actual val URLMapper: Mapper<URL, URLBuilder> = object : Mapper<URL, URLBuilder> {
override val inputKClass: KClass<URL>
get() = URL::class
override val outputKClass: KClass<Url>
get() = Url::class
override val outputKClass: KClass<URLBuilder>
get() = URLBuilder::class

override fun map(input: URL): Url = StringMapper.map(input.absoluteString()!!)
override fun map(input: URL): URLBuilder = StringMapper.map(input.absoluteString()!!)
}


internal actual val URIMapper: Mapper<URI, Url> = object : Mapper<URI, Url> {
internal actual val URIMapper: Mapper<URI, URLBuilder> = object : Mapper<URI, URLBuilder> {
override val inputKClass: KClass<URI>
get() = URI::class
override val outputKClass: KClass<Url>
get() = Url::class
override val outputKClass: KClass<URLBuilder>
get() = URLBuilder::class

override fun map(input: URI): Url = StringMapper.map(input.str)
override fun map(input: URI): URLBuilder = StringMapper.map(input.str)
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ import java.io.File
import kotlin.reflect.KClass

/**
* Fetcher that fetches [ByteReadChannel] from the localhost using [Url].
* Fetcher that fetches [ByteReadChannel] from the localhost using [URLBuilder].
*/
internal actual val FileUrlFetcher = object : Fetcher<Url> {
override val inputDataKClass: KClass<Url> = Url::class
internal actual val FileUrlFetcher = object : Fetcher<URLBuilder> {
override val inputDataKClass: KClass<URLBuilder> = URLBuilder::class

override val source: DataSource = DataSource.Disk

override val Url.isSupported: Boolean
override val URLBuilder.isSupported: Boolean
get() = protocol.name == "file"

override fun fetch(data: Url, resourceConfig: ResourceConfig): Flow<Resource<ByteReadChannel>> {
return FileFetcher.fetch(File(data.toURI()), resourceConfig)
override fun fetch(data: URLBuilder, resourceConfig: ResourceConfig): Flow<Resource<ByteReadChannel>> {
return FileFetcher.fetch(File(data.build().toURI()), resourceConfig)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,20 +5,20 @@ import io.kamel.core.utils.URL
import io.ktor.http.*
import kotlin.reflect.KClass

internal actual val URLMapper: Mapper<URL, Url> = object : Mapper<URL, Url> {
internal actual val URLMapper: Mapper<URL, URLBuilder> = object : Mapper<URL, URLBuilder> {
override val inputKClass: KClass<URL>
get() = URL::class
override val outputKClass: KClass<Url>
get() = Url::class
override val outputKClass: KClass<URLBuilder>
get() = URLBuilder::class

override fun map(input: URL): Url = Url(input.toURI())
override fun map(input: URL): URLBuilder = URLBuilder().takeFrom(input)
}

internal actual val URIMapper: Mapper<URI, Url> = object : Mapper<URI, Url> {
internal actual val URIMapper: Mapper<URI, URLBuilder> = object : Mapper<URI, URLBuilder> {
override val inputKClass: KClass<URI>
get() = URI::class
override val outputKClass: KClass<Url>
get() = Url::class
override val outputKClass: KClass<URLBuilder>
get() = URLBuilder::class

override fun map(input: URI): Url = Url(input)
override fun map(input: URI): URLBuilder = URLBuilder().takeFrom(input)
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public class KamelConfigBuilder {
}

/**
* Adds a Http [Url] fetcher to the [KamelConfigBuilder] using the specified [client].
* Adds a Http [URLBuilder] fetcher to the [KamelConfigBuilder] using the specified [client].
*/
public fun KamelConfigBuilder.httpUrlFetcher(client: HttpClient): Unit = fetcher(HttpUrlFetcher(client))

Expand All @@ -87,7 +87,7 @@ public fun KamelConfigBuilder.httpUrlFetcher(client: HttpClient): Unit = fetcher
public fun KamelConfigBuilder.httpFetcher(client: HttpClient): Unit = fetcher(HttpUrlFetcher(client))

/**
* Adds a Http [Url] fetcher to the [KamelConfigBuilder] using the specified [engine]
* Adds a Http [URLBuilder] fetcher to the [KamelConfigBuilder] using the specified [engine]
* and an optional [block] for configuring this client.
*/
public fun KamelConfigBuilder.httpUrlFetcher(
Expand All @@ -96,15 +96,15 @@ public fun KamelConfigBuilder.httpUrlFetcher(
): Unit = fetcher(HttpUrlFetcher(HttpClient(engine, block)))

/**
* Adds a Http [Url] fetcher to the [KamelConfigBuilder] by loading an [HttpClientEngine] from [ServiceLoader]
* Adds a Http [URLBuilder] fetcher to the [KamelConfigBuilder] by loading an [HttpClientEngine] from [ServiceLoader]
* and an optional [block] for configuring this client.
*/
public fun KamelConfigBuilder.httpUrlFetcher(
block: HttpClientConfig<*>.() -> Unit = {}
): Unit = fetcher(HttpUrlFetcher(HttpClient(block)))

/**
* Adds a Localhost [Url] fetcher to the [KamelConfigBuilder].
* Adds a Localhost [URLBuilder] fetcher to the [KamelConfigBuilder].
*/
public fun KamelConfigBuilder.fileUrlFetcher(): Unit = fetcher(FileUrlFetcher)

Expand All @@ -114,17 +114,17 @@ public fun KamelConfigBuilder.fileUrlFetcher(): Unit = fetcher(FileUrlFetcher)
public fun KamelConfigBuilder.fileFetcher(): Unit = fetcher(FileFetcher)

/**
* Adds a [String] to [Url] mapper to the [KamelConfigBuilder].
* Adds a [String] to [URLBuilder] mapper to the [KamelConfigBuilder].
*/
public fun KamelConfigBuilder.stringMapper(): Unit = mapper(StringMapper)

/**
* Adds a [URI] to [Url] mapper to the [KamelConfigBuilder].
* Adds a [URI] to [URLBuilder] mapper to the [KamelConfigBuilder].
*/
public fun KamelConfigBuilder.uriMapper(): Unit = mapper(URIMapper)

/**
* Adds a [URL] to [Url] mapper to the [KamelConfigBuilder].
* Adds a [URL] to [URLBuilder] mapper to the [KamelConfigBuilder].
*/
public fun KamelConfigBuilder.urlMapper(): Unit = mapper(URLMapper)

Expand All @@ -147,4 +147,4 @@ public fun KamelConfigBuilder.takeFrom(config: KamelConfig): KamelConfigBuilder
config.mappers.values.flatten().forEach { mapper(it) }

return this
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ import io.ktor.http.*
import io.ktor.utils.io.*

/**
* Fetcher that fetches [ByteReadChannel] from the localhost using [Url].
* Fetcher that fetches [ByteReadChannel] from the localhost using [URLBuilder].
*/
internal expect val FileUrlFetcher: Fetcher<Url>
internal expect val FileUrlFetcher: Fetcher<URLBuilder>
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,20 @@ import kotlinx.coroutines.flow.channelFlow
import kotlin.reflect.KClass

/**
* Fetcher that fetches [ByteReadChannel] from network using [Url].
* Fetcher that fetches [ByteReadChannel] from network using [URLBuilder].
*/
internal class HttpUrlFetcher(private val client: HttpClient) : Fetcher<Url> {
internal class HttpUrlFetcher(private val client: HttpClient) : Fetcher<URLBuilder> {

override val inputDataKClass: KClass<Url> = Url::class
override val inputDataKClass: KClass<URLBuilder> = URLBuilder::class

override val source: DataSource = DataSource.Network

override val Url.isSupported: Boolean
override val URLBuilder.isSupported: Boolean
get() = protocol.name == "https" || protocol.name == "http"

override fun fetch(
data: Url, resourceConfig: ResourceConfig
data: URLBuilder,
resourceConfig: ResourceConfig
): Flow<Resource<ByteReadChannel>> = channelFlow {
val response = client.request {
onDownload { bytesSentTotal, contentLength ->
Expand All @@ -36,10 +37,10 @@ internal class HttpUrlFetcher(private val client: HttpClient) : Fetcher<Url> {
if (progress != null) send(Resource.Loading(progress, source))
}
takeFrom(resourceConfig.requestData)
url(data)
url.takeFrom(data)
}
val bytes = response.bodyAsChannel()
send(Resource.Success(bytes, source))
}

}
}
16 changes: 8 additions & 8 deletions kamel-core/src/commonMain/kotlin/io/kamel/core/mapper/Mappers.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@ import io.kamel.core.utils.URL
import io.ktor.http.*
import kotlin.reflect.KClass

internal val StringMapper: Mapper<String, Url> = object : Mapper<String, Url> {
internal val StringMapper: Mapper<String, URLBuilder> = object : Mapper<String, URLBuilder> {
override val inputKClass: KClass<String>
get() = String::class
override val outputKClass: KClass<Url>
get() = Url::class
override val outputKClass: KClass<URLBuilder>
get() = URLBuilder::class

override fun map(input: String): Url {
override fun map(input: String): URLBuilder {
val regex = Regex("^file:/+(?!/)")
return if (regex.containsMatchIn(input)) {
// Replace 'file:/' or `file:///` with 'file:///' using regex
// https://youtrack.jetbrains.com/issue/KTOR-6709
Url(input.replaceFirst(regex, "file:///"))
URLBuilder(input.replaceFirst(regex, "file:///"))
} else {
// If input does not match regex and does not start with '/', use it as is
Url(input)
URLBuilder(input)
}
}

}

internal expect val URLMapper: Mapper<URL, Url>
internal expect val URLMapper: Mapper<URL, URLBuilder>

internal expect val URIMapper: Mapper<URI, Url>
internal expect val URIMapper: Mapper<URI, URLBuilder>
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package io.kamel.core.config

import io.kamel.core.fetcher.HttpUrlFetcher
import io.kamel.core.loadImageBitmapResource
import io.ktor.client.*
import io.ktor.client.engine.mock.*
import io.ktor.client.plugins.*
import io.ktor.http.*
import kotlinx.coroutines.flow.toList
import kotlinx.coroutines.test.runTest
import kotlin.coroutines.EmptyCoroutineContext
import kotlin.test.Test
import kotlin.test.assertEquals

class DefaultRequestConfigTest {

@Test
fun testDefaultRequestWithURLBuilder() = runTest {
var url = ""
KamelConfig {
stringMapper()
fakeImageBitmapDecoder()
fetcher(
HttpUrlFetcher(
HttpClient(
MockEngine { request ->
url = request.url.toString()
respondError(HttpStatusCode.NotFound)
}
) {
defaultRequest {
url("https://kamel.media")
}
})
)
}.loadImageBitmapResource(
data = URLBuilder("image.jpg"),
resourceConfig = ResourceConfigBuilder(EmptyCoroutineContext).build()
).toList()
assertEquals("https://kamel.media/image.jpg", url)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,21 @@ class KamelConfigUtilsTest {
fun testMapStringInput() {
val result = config.mapInput(TestStringUrl, String::class)

assertTrue(result is Url)
assertTrue(result is URLBuilder)
}

@Test
fun testMapURLInput() {
val result = config.mapInput(createURL(TestStringUrl), URL::class)

assertTrue(result is Url)
assertTrue(result is URLBuilder)
}

@Test
fun testMapURIInput() {
val result = config.mapInput(createURI(TestStringUrl), URI::class)

assertTrue(result is Url)
assertTrue(result is URLBuilder)
}

@Test
Expand All @@ -60,12 +60,12 @@ class KamelConfigUtilsTest {
stringMapper()
}
val result = twoMappersConfig.mapInput(TestStringUrl, String::class)
assertTrue(result is Url)
assertTrue(result is URLBuilder)
}

@Test
fun testFindHttpUrlFetcher() {
val fetcher = config.findFetcherFor(Url(TestStringUrl))
val fetcher = config.findFetcherFor(URLBuilder(TestStringUrl))

assertTrue { fetcher is HttpUrlFetcher }
}
Expand Down
Loading