Skip to content

Commit

Permalink
Fix native targets
Browse files Browse the repository at this point in the history
  • Loading branch information
Natan Vieira do Nascimento committed Aug 8, 2023
1 parent 83cc805 commit aada090
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 63 deletions.
30 changes: 14 additions & 16 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,8 @@ kotlin {
}
}

val hostOs = System.getProperty("os.name")
var isNativeUnsupported = false
when (hostOs) {
"Mac OS X" -> macosX64("native")
"Linux" -> linuxX64("native")
else -> isNativeUnsupported = true
}
linuxX64()
macosX64()

sourceSets {
val commonMain by getting {
Expand Down Expand Up @@ -85,18 +80,21 @@ kotlin {
}
}

if (!isNativeUnsupported) {
val nativeMain by getting {
dependsOn(commonMain)
dependencies {
implementation(libs.ktor.client.engine.cio)
}
val nativeMain by creating {
dependsOn(commonMain)
dependencies {
implementation(libs.ktor.client.engine.cio)
}
}

val nativeTest by getting {
dependsOn(commonTest)
}
val nativeTest by creating {
dependsOn(commonTest)
}

val linuxX64Main by getting { dependsOn(nativeMain) }
val linuxX64Test by getting { dependsOn(nativeTest) }
val macosX64Main by getting { dependsOn(nativeMain) }
val macosX64Test by getting { dependsOn(nativeTest) }
}
}

Expand Down
59 changes: 20 additions & 39 deletions src/commonMain/kotlin/me/devnatan/yoki/io/Http.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,21 +21,13 @@ import io.ktor.serialization.kotlinx.json.json
import kotlinx.serialization.json.Json
import me.devnatan.yoki.GenericDockerErrorResponse
import me.devnatan.yoki.Yoki
import me.devnatan.yoki.YokiConfig
import me.devnatan.yoki.YokiResponseException
import okio.ByteString.Companion.decodeHex
import okio.ByteString.Companion.encodeUtf8

internal expect fun <T : HttpClientEngineConfig> HttpClientConfig<out T>.configureHttpClient(
client: Yoki,
)

private fun checkSocketPath(config: YokiConfig) {
check(config.socketPath.isNotBlank()) { "Socket path cannot be blank" }
}
internal expect fun <T : HttpClientEngineConfig> HttpClientConfig<out T>.configureHttpClient(client: Yoki)

internal fun createHttpClient(client: Yoki): HttpClient {
checkSocketPath(client.config)
check(client.config.socketPath.isNotBlank()) { "Socket path cannot be blank" }
return HttpClient {
expectSuccess = true
install(ContentNegotiation) {
Expand All @@ -45,8 +37,8 @@ internal fun createHttpClient(client: Yoki): HttpClient {
},
)
}
// TODO set Yoki version on user agent
install(UserAgent) { agent = "Yoki/0.0.1" }

install(UserAgent) { agent = "Yoki" }
configureHttpClient(client)

HttpResponseValidator {
Expand Down Expand Up @@ -78,33 +70,22 @@ internal fun createHttpClient(client: Yoki): HttpClient {
}
}

internal fun decodeHostname(hostname: String): String {
return hostname
.substring(0, hostname.indexOf(ENCODED_HOSTNAME_SUFFIX))
.decodeHex()
.utf8()
}

private fun createUrlBuilder(socketPath: String): URLBuilder {
return if (isUnixSocket(socketPath)) {
URLBuilder(
protocol = URLProtocol.HTTP,
port = DOCKER_SOCKET_PORT,
host = socketPath.substringAfter(UNIX_SOCKET_PREFIX).encodeUtf8().hex() + ENCODED_HOSTNAME_SUFFIX,
)
} else {
val url = Url(socketPath)
URLBuilder(
protocol = URLProtocol.HTTP,
host = url.host,
port = url.port,
)
}
private fun createUrlBuilder(socketPath: String): URLBuilder = if (isUnixSocket(socketPath)) {
URLBuilder(
protocol = URLProtocol.HTTP,
port = DOCKER_SOCKET_PORT,
host = socketPath.substringAfter(UNIX_SOCKET_PREFIX).encodeUtf8().hex() + ENCODED_HOSTNAME_SUFFIX,
)
} else {
val url = Url(socketPath)
URLBuilder(
protocol = URLProtocol.HTTP,
host = url.host,
port = url.port,
)
}

internal fun <T> Result<T>.mapFailureToHttpStatus(
statuses: Map<HttpStatusCode, (YokiResponseException) -> Throwable>,
) = onFailure { exception ->
internal fun handleHttpFailure(exception: Throwable, statuses: Map<HttpStatusCode, (YokiResponseException) -> Throwable>) {
if (exception !is YokiResponseException) {
throw exception
}
Expand All @@ -115,12 +96,12 @@ internal fun <T> Result<T>.mapFailureToHttpStatus(

throw resourceException
?.invoke(exception)
?.also { it.addSuppressed(exception) }
?.also { root -> root.addSuppressed(exception) }
?: exception
}

// TODO use Ktor exception handler instead
internal inline fun <T> requestCatching(
vararg errors: Pair<HttpStatusCode, (YokiResponseException) -> Throwable>,
request: () -> T,
) = runCatching(request).mapFailureToHttpStatus(errors.toMap()).getOrThrow()
) = runCatching(request).onFailure { exception -> handleHttpFailure(exception, errors.toMap()) }.getOrThrow()
4 changes: 1 addition & 3 deletions src/jvmMain/kotlin/me/devnatan/yoki/io/Http.jvm.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ import io.ktor.client.engine.okhttp.OkHttpConfig
import me.devnatan.yoki.Yoki
import java.util.concurrent.TimeUnit

internal actual fun <T : HttpClientEngineConfig> HttpClientConfig<out T>.configureHttpClient(
client: Yoki,
) {
internal actual fun <T : HttpClientEngineConfig> HttpClientConfig<out T>.configureHttpClient(client: Yoki) {
engine {
// ensure that current engine is OkHttp, cannot use CIO due to a Ktor Client bug related to data streaming
// https://youtrack.jetbrains.com/issue/KTOR-2494
Expand Down
8 changes: 8 additions & 0 deletions src/jvmMain/kotlin/me/devnatan/yoki/io/Sockets.jvm.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package me.devnatan.yoki.io

import okhttp3.Dns
import okio.ByteString.Companion.decodeHex
import org.newsclub.net.unix.AFUNIXSocketAddress
import org.newsclub.net.unix.AFUNIXSocketFactory
import java.net.InetAddress
Expand All @@ -24,6 +25,13 @@ internal class SocketDns(private val isUnixSocket: Boolean) : Dns {
}

internal class UnixSocketFactory : AFUNIXSocketFactory() {
private fun decodeHostname(hostname: String): String {
return hostname
.substring(0, hostname.indexOf(ENCODED_HOSTNAME_SUFFIX))
.decodeHex()
.utf8()
}

override fun addressFromHost(host: String, port: Int): AFUNIXSocketAddress {
val socketPath = decodeHostname(host)
val socketFile = Paths.get(socketPath) ?: error("Unable to connect to unix socket @ $socketPath")
Expand Down
1 change: 0 additions & 1 deletion src/nativeMain/kotlin/me/devnatan/yoki/Platform.native.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import platform.posix.getenv
* Returns if the current platform is a UNIX-based platform.
*/
internal actual fun isUnixPlatform(): Boolean {
// TODO check if current platform is unix
return true
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,9 @@
package me.devnatan.yoki.net
package me.devnatan.yoki.io

import io.ktor.client.HttpClientConfig
import io.ktor.client.engine.HttpClientEngineConfig
import me.devnatan.yoki.Yoki

internal actual fun <T : HttpClientEngineConfig> HttpClientConfig<out T>.configureHttpClient(
client: Yoki,
) {
internal actual fun <T : HttpClientEngineConfig> HttpClientConfig<out T>.configureHttpClient(client: Yoki) {
TODO("Native HTTP client is not supported for now")
}

0 comments on commit aada090

Please sign in to comment.