Integrate Ktor HTTP clients and repositories for Veranstalter and Turnier features:
- Add `ApiRoutes` for central backend routing configuration. - Implement `DefaultVeranstalterRepository` and `DefaultTurnierRepository` with Ktor clients. - Add domain models (`Turnier`, `Bewerb`, `Abteilung`, `Veranstalter`) and respective repository interfaces. - Replace fake VeranstalterRepository with real implementation. - Update DI with `veranstalterModule` and HTTP client injection. - Simplify TokenProvider and update HttpClient setup (timeouts, retries, logging). - Mark roadmap tasks B-2 as partially complete.
This commit is contained in:
+21
@@ -0,0 +1,21 @@
|
||||
package at.mocode.frontend.core.network
|
||||
|
||||
/**
|
||||
* Zentrale API-Routen-Konfiguration. Versionierung erfolgt über den Prefix /api/v3.
|
||||
*/
|
||||
object ApiRoutes {
|
||||
const val API_PREFIX = "/api/v3"
|
||||
|
||||
object Veranstalter {
|
||||
const val ROOT = "$API_PREFIX/veranstalter"
|
||||
}
|
||||
|
||||
object Turniere {
|
||||
const val ROOT = "$API_PREFIX/turniere"
|
||||
fun bewerbe(turnierId: Long): String = "$ROOT/$turnierId/bewerbe"
|
||||
}
|
||||
|
||||
object Bewerbe {
|
||||
fun abteilungen(bewerbId: Long): String = "$API_PREFIX/bewerbe/$bewerbId/abteilungen"
|
||||
}
|
||||
}
|
||||
+1
@@ -0,0 +1 @@
|
||||
// Removed: superseded by NetworkModule.kt
|
||||
+20
-23
@@ -13,9 +13,7 @@ import org.koin.dsl.module
|
||||
/**
|
||||
* Schnittstelle zur Token-Bereitstellung – entkoppelt core-network von core-auth.
|
||||
*/
|
||||
interface TokenProvider {
|
||||
fun getAccessToken(): String?
|
||||
}
|
||||
interface TokenProvider { fun getAccessToken(): String? }
|
||||
|
||||
/**
|
||||
* Koin-Modul mit zwei HttpClient-Instanzen:
|
||||
@@ -28,16 +26,15 @@ val networkModule = module {
|
||||
single(named("baseHttpClient")) {
|
||||
HttpClient {
|
||||
install(ContentNegotiation) {
|
||||
json(Json { ignoreUnknownKeys = true; isLenient = true; encodeDefaults = true })
|
||||
}
|
||||
install(Logging) {
|
||||
logger = object : Logger {
|
||||
override fun log(message: String) {
|
||||
println("[baseClient] $message")
|
||||
json(
|
||||
Json {
|
||||
ignoreUnknownKeys = true
|
||||
explicitNulls = false
|
||||
coerceInputValues = true
|
||||
}
|
||||
}
|
||||
level = LogLevel.INFO
|
||||
)
|
||||
}
|
||||
install(Logging) { logger = Logger.SIMPLE; level = LogLevel.NONE }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,29 +44,29 @@ val networkModule = module {
|
||||
|
||||
HttpClient {
|
||||
install(ContentNegotiation) {
|
||||
json(Json { ignoreUnknownKeys = true; isLenient = true; encodeDefaults = true })
|
||||
json(
|
||||
Json {
|
||||
ignoreUnknownKeys = true
|
||||
explicitNulls = false
|
||||
coerceInputValues = true
|
||||
}
|
||||
)
|
||||
}
|
||||
install(HttpTimeout) {
|
||||
// Defaults laut Spezifikation (Prod)
|
||||
connectTimeoutMillis = 5_000
|
||||
requestTimeoutMillis = 15_000
|
||||
connectTimeoutMillis = 10_000
|
||||
socketTimeoutMillis = 15_000
|
||||
socketTimeoutMillis = 30_000
|
||||
}
|
||||
install(HttpRequestRetry) {
|
||||
maxRetries = 3
|
||||
maxRetries = 2
|
||||
retryIf { _, response -> response.status.value.let { it == 0 || it >= 500 } }
|
||||
exponentialDelay()
|
||||
}
|
||||
defaultRequest {
|
||||
url(NetworkConfig.baseUrl.trimEnd('/'))
|
||||
}
|
||||
install(Logging) {
|
||||
logger = object : Logger {
|
||||
override fun log(message: String) {
|
||||
println("[apiClient] $message")
|
||||
}
|
||||
}
|
||||
level = LogLevel.INFO
|
||||
}
|
||||
install(Logging) { logger = Logger.SIMPLE; level = LogLevel.NONE }
|
||||
}.also { client ->
|
||||
// Bearer-Token pro Request dynamisch injizieren (lazy, damit kein Circular-Dependency)
|
||||
client.plugin(HttpSend).intercept { request ->
|
||||
|
||||
Reference in New Issue
Block a user