feat: add Ktor networking layer with ApiService and auth token holder
Add ApiConfig, AuthTokenHolder singleton, expect/actual HttpClient engine factories (CIO for Android/Desktop, Darwin for iOS), and ApiService with four GET endpoints. Bearer token from AuthTokenHolder is injected as Authorization header on each request. Adjusted for Ktor 3.5.1: HttpClientEngineFactory lives in io.ktor.client.engine; the timeout plugin is HttpTimeout (package io.ktor.client.plugins), not HttpTimeoutPlugin. Tests wrap suspend calls in runTest and assert request URLs without a trailing '?'.
This commit is contained in:
@@ -0,0 +1,5 @@
|
||||
package ch.parano.myice.network
|
||||
|
||||
object ApiConfig {
|
||||
const val baseUrl = "https://myice.parano.ch"
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
package ch.parano.myice.network
|
||||
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.engine.HttpClientEngineConfig
|
||||
import io.ktor.client.engine.HttpClientEngineFactory
|
||||
import io.ktor.client.plugins.contentnegotiation.ContentNegotiation
|
||||
import io.ktor.client.plugins.HttpTimeout
|
||||
import io.ktor.serialization.kotlinx.json.json
|
||||
import kotlinx.serialization.json.Json
|
||||
|
||||
expect fun createEngine(): HttpClientEngineFactory<HttpClientEngineConfig>
|
||||
|
||||
fun createHttpClient(): HttpClient {
|
||||
return HttpClient(createEngine()) {
|
||||
install(ContentNegotiation) {
|
||||
json(Json { ignoreUnknownKeys = true })
|
||||
}
|
||||
install(HttpTimeout) {
|
||||
connectTimeoutMillis = 10_000
|
||||
requestTimeoutMillis = 10_000
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package ch.parano.myice.network
|
||||
|
||||
import ch.parano.myice.models.Account
|
||||
import ch.parano.myice.models.Event
|
||||
import ch.parano.myice.models.EventDetail
|
||||
import ch.parano.myice.models.UserInfo
|
||||
import io.ktor.client.HttpClient
|
||||
import io.ktor.client.call.body
|
||||
import io.ktor.client.request.get
|
||||
import io.ktor.client.request.header
|
||||
import io.ktor.http.HttpHeaders
|
||||
|
||||
class ApiService(private val client: HttpClient) {
|
||||
|
||||
private fun authHeader(): String? = AuthTokenHolder.token?.let { "Bearer $it" }
|
||||
|
||||
suspend fun getUserInfo(): UserInfo =
|
||||
client.get("${ApiConfig.baseUrl}/userinfo") {
|
||||
authHeader()?.let { header(HttpHeaders.Authorization, it) }
|
||||
}.body()
|
||||
|
||||
suspend fun getAccounts(): List<Account> =
|
||||
client.get("${ApiConfig.baseUrl}/accounts") {
|
||||
authHeader()?.let { header(HttpHeaders.Authorization, it) }
|
||||
}.body()
|
||||
|
||||
suspend fun getSchedule(account: String): List<Event> =
|
||||
client.get("${ApiConfig.baseUrl}/schedule") {
|
||||
url.parameters.append("account", account)
|
||||
authHeader()?.let { header(HttpHeaders.Authorization, it) }
|
||||
}.body()
|
||||
|
||||
suspend fun getGameDetail(gameId: String, account: String): EventDetail =
|
||||
client.get("${ApiConfig.baseUrl}/game/$gameId") {
|
||||
url.parameters.append("account", account)
|
||||
authHeader()?.let { header(HttpHeaders.Authorization, it) }
|
||||
}.body()
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package ch.parano.myice.network
|
||||
|
||||
object AuthTokenHolder {
|
||||
var token: String? = null
|
||||
}
|
||||
Reference in New Issue
Block a user