From b342ae85c6bed8d58b0806c2670209b8492155e2 Mon Sep 17 00:00:00 2001 From: yumoqing Date: Mon, 18 May 2026 09:31:34 +0800 Subject: [PATCH] fix: rewrite SageClient and BricksHttp to use URL-encoded string body instead of FormDataContent (not available in Ktor common) --- .../kotlin/com/bricks/mp/core/BricksHttp.kt | 7 +++++-- .../kotlin/com/bricks/mp/sage/SageClient.kt | 16 +++++----------- 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/shared/src/commonMain/kotlin/com/bricks/mp/core/BricksHttp.kt b/shared/src/commonMain/kotlin/com/bricks/mp/core/BricksHttp.kt index fe9da5e..527f056 100644 --- a/shared/src/commonMain/kotlin/com/bricks/mp/core/BricksHttp.kt +++ b/shared/src/commonMain/kotlin/com/bricks/mp/core/BricksHttp.kt @@ -5,7 +5,6 @@ import io.ktor.client.engine.cio.* import io.ktor.client.plugins.cookies.* import io.ktor.client.request.* import io.ktor.client.statement.* -import io.ktor.http.content.FormDataContent import io.ktor.http.* import kotlinx.serialization.json.* @@ -83,8 +82,12 @@ class BricksHttp(private val context: BricksContext? = null) { form: Parameters, authToken: String = "" ): String { + val formBody = form.flattenEntries().joinToString("&") { (k, v) -> + "${encodeURLParameter(k)}=${encodeURLParameter(v)}" + } val response = client.post(url) { - setBody(FormDataContent(form)) + contentType(ContentType.Application.FormUrlEncoded) + setBody(formBody) if (authToken.isNotEmpty()) { header(HttpHeaders.Authorization, "Bearer $authToken") } diff --git a/shared/src/commonMain/kotlin/com/bricks/mp/sage/SageClient.kt b/shared/src/commonMain/kotlin/com/bricks/mp/sage/SageClient.kt index d72b6e0..dc3938f 100644 --- a/shared/src/commonMain/kotlin/com/bricks/mp/sage/SageClient.kt +++ b/shared/src/commonMain/kotlin/com/bricks/mp/sage/SageClient.kt @@ -7,9 +7,7 @@ import io.ktor.client.engine.cio.* import io.ktor.client.plugins.cookies.* import io.ktor.client.request.* import io.ktor.client.statement.* -import io.ktor.http.content.FormDataContent import io.ktor.http.* -import kotlinx.coroutines.flow.asStateFlow import kotlinx.coroutines.sync.Mutex import kotlinx.coroutines.sync.withLock import kotlinx.serialization.json.* @@ -57,13 +55,11 @@ class SageClient { _loginError.value = null try { val url = "$baseUrl/rbac/user/userpassword_login.dspy" - val formParameters = Parameters.build { - append("username", username) - append("passwd", password) - } + val formBody = "username=${encodeURLParameter(username)}&passwd=${encodeURLParameter(password)}" val response = client.post(url) { - setBody(FormDataContent(formParameters)) + contentType(ContentType.Application.FormUrlEncoded) + setBody(formBody) } val body = response.bodyAsText() @@ -142,7 +138,7 @@ class SageClient { path: String, params: Map = emptyMap(), method: String = "GET", - formBody: Parameters? = null, + formBody: String = "", jsonBody: JsonObject? = null ): Result = mutex.withLock { try { @@ -158,7 +154,7 @@ class SageClient { contentType(ContentType.Application.Json) setBody(jsonBody) } - formBody != null -> { + formBody.isNotEmpty() -> { contentType(ContentType.Application.FormUrlEncoded) setBody(formBody) } @@ -197,8 +193,6 @@ class SageClient { */ suspend fun logout() = mutex.withLock { try { - // 清除 cookies - cookieStorage.get(URLBuilder(baseUrl).build()) _isLoggedIn.value = false println("[Sage] Logged out") } catch (e: Exception) {