在我的移动应用程序中,我有一个单例 Ktor HttpClient,其不记名身份验证配置如下:
HttpClient(\xe2\x80\xa6) {\n install(Auth) {\n bearer {\n sendWithoutRequest { requestBuilder -> some condition }\n loadTokens(tokensStorage::getTokens)\n refreshTokens {\n performTokenRefresh(oldTokens.refreshToken)\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n现在考虑以下流程:
\ntokenStorage无效。HttpClient令牌tokenStorage,请求失败并返回 401。HttpClient执行刷新,但也失败,因为刷新令牌无效。tokenStorage.HttpClient不再尝试调用loadTokens。确实,从源代码来看,loadTokens只被调用一次,然后就不会再被调用。我找到了解决该问题的几种方法。
\n第一个是手动BearerAuthProvider从HttpClient自己清除令牌,如以下代码片段所示,但这似乎是一种黑客解决方法:
httpClient.plugin(Auth).providers\n .filterIsInstance<BearerAuthProvider>()\n .first().clearToken()\nRun Code Online (Sandbox Code Playgroud)\ntokenStorage另一种方法是从 my in手动加载当前令牌refreshToken并忽略传入的内容this@refreshTokens.oldTokens …
我正在使用Ktor 1.2.2,并且有一个 InputStream 对象,我想将其用作我接下来发出的 HttpClient 请求的主体。直到 Ktor 0.95 为止,这个InputStreamContent对象似乎就是这样做的,但它已在版本 1.0.0 中从 Ktor 中删除(遗憾的是无法弄清楚原因)。
我可以使用 ByteArrayContent 使其工作(请参见下面的代码),但我宁愿找到一个不需要将整个 InputStream 加载到内存中的解决方案......
ByteArrayContent(input.readAllBytes())
Run Code Online (Sandbox Code Playgroud)
此代码是一个简单的测试用例,模拟我想要实现的目标:
val file = File("c:\\tmp\\foo.pdf")
val inputStream = file.inputStream()
val client = HttpClient(CIO)
client.call(url) {
method = HttpMethod.Post
body = inputStream // TODO: Make this work :(
}
// [... other code that uses the response below]
Run Code Online (Sandbox Code Playgroud)
如果我遗漏了任何相关信息,请告诉我,
谢谢!
我正在尝试上传多个文件。
val ktorVersion = "1.5.0"
val serializationVersion = "1.0.1"
Run Code Online (Sandbox Code Playgroud)
我就是这样做的:
override suspend fun uploadFiles(
binaryFiles: Map<String,ByteArray>
): BaseResponse<List<String>> {
return client.submitForm {
url(fileUploadUrl)
method = HttpMethod.Post
body = MultiPartFormDataContent(
formData {
headers{
append("Content-Type", "application/json")
append("Authorization", "Bearer $token}")
}
binaryFiles.entries.forEach {
append(
key = "files",
value = it.value,
headers = Headers.build {
append(HttpHeaders.ContentDisposition, "filename=${it.key}")
}
)
}
}
)
}
}
Run Code Online (Sandbox Code Playgroud)
但它抛出异常
kotlinx.serialization.SerializationException: Serializer for class 'MultiPartFormDataContent' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
at …Run Code Online (Sandbox Code Playgroud) android ktor kotlinx.serialization ktor-client kotlin-multiplatform-mobile
我正在尝试连接到一个具有来自内部测试环境的自签名证书的服务,该证书仅在原型设计期间存在。Ktor 客户端失败并显示
javax.net.ssl.SSLHandshakeException: PKIX path building failed:
sun.security.provider.certpath.SunCertPathBuilderException:
unable to find valid certification path to requested target
Run Code Online (Sandbox Code Playgroud)
在这种情况下如何禁用证书验证?
当我发现这个文件时,我一直在 github 上查看 Ktor-client 源代码,试图在做出贡献之前理解它。我看到 java 语法,但我不明白为什么它有扩展名 (.api),以及它的用途。任何参考链接的答案将不胜感激。
我有一个 api,它在发送错误请求时返回带有正确错误信息的错误正文。例如,我得到状态代码 400 和以下正文 -
{
"errorCode": 1011,
"errorMessage": "Unable to get Child information"
}
Run Code Online (Sandbox Code Playgroud)
现在,当我为此在多平台模块中编写 ktor 客户端时,我会在响应验证器中捕获它,例如 -
HttpResponseValidator {
validateResponse {
val statusCode = it.status.value
when (statusCode) {
in 300..399 -> print(it.content.toString())
in 400..499 -> {
print(it.content.toString())
throw ClientRequestException(it)
}
in 500..599 -> print(it.content.toString())
}
}
handleResponseException {
print(it.message)
}
}
Run Code Online (Sandbox Code Playgroud)
我在这里的查询是我不能够访问响应误差身体任一validateResponse或handleResponseException。有没有办法可以捕获并解析它以获取服务器发送的实际错误?
我试图在 Kotlin/MPP(多平台)项目和 JVM 目标功能中使用ktor 客户端,基本身份验证似乎没有效果。
import io.ktor.client.HttpClient
import io.ktor.client.features.ResponseException
import io.ktor.client.features.auth.Auth
import io.ktor.client.features.auth.providers.basic
import io.ktor.client.features.json.JsonFeature
import io.ktor.client.features.json.serializer.KotlinxSerializer
import io.ktor.client.features.logging.DEFAULT
import io.ktor.client.features.logging.LogLevel
import io.ktor.client.features.logging.Logger
import io.ktor.client.features.logging.Logging
import io.ktor.client.request.get
import io.ktor.client.request.header
import kotlinx.coroutines.runBlocking
import java.util.*
fun main() = runBlocking {
val client = HttpClient {
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.HEADERS
}
install(JsonFeature) {
serializer = KotlinxSerializer()
}
install(Auth) {
basic {
username = "user"
password = "pass"
}
}
}
val url = "https://en.wikipedia.org/wiki/Main_Page" …Run Code Online (Sandbox Code Playgroud) 所以我是 Kotlin Multiplatform Mobile 和一般移动开发的新手。我正在尝试按照KMM 教程中的本教程在我的项目中使用 Ktor。
添加依赖后,如下图build.gradle.kts(commonMain、androidMain、iosMain的依赖):
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
plugins {
kotlin("multiplatform")
id("com.android.library")
}
kotlin {
android()
ios {
binaries {
framework {
baseName = "shared"
}
}
}
val ktorVersion = "1.5.2"
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.ktor:ktor-client-core:$ktorVersion")
}
}
val commonTest by getting {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
}
}
val androidMain by getting {
dependencies {
implementation ("io.ktor:ktor-client-android:$ktorVersion")
}
}
val androidTest by getting {
dependencies {
implementation(kotlin("test-junit"))
implementation("junit:junit:4.13")
} …Run Code Online (Sandbox Code Playgroud) kotlin android-gradle-plugin ktor kotlin-multiplatform ktor-client
我正在将 Android 版 Ktor 客户端与插件一起使用:io.ktor:ktor-client-auth:1.6.4。当前的实现与此代码片段类似。
现在我想在单击按钮后删除令牌时实现“注销”功能,问题是......如何实现?
我正在尝试将此 JSON 响应反序列化为一个对象,并且我的一个键上有一个连字符。不幸的是,Kotlin 不支持变量名称中的连字符,这就是我使用 @SerializedName() 但它现在仍然有效的原因。有什么线索可以解释为什么吗?
JSON 响应
[
{
"dateCreated": "07-22-2021",
"comments": "Comment",
"vehicle_type": "Sedan",
"name": "Leagacy Nissan Template",
"template-type": "", //this is giving me the problem
"template_uses_type": "Both"
...
}
]
Run Code Online (Sandbox Code Playgroud)
我的对象:
@Serializable
data class SpinDataResponse(
val dateCreated:String,
val comments: String,
val vehicle_type:String,
val name:String,
@SerializedName("template-type") val template_type:String,
val template_uses_type:String,
...
)
Run Code Online (Sandbox Code Playgroud)
错误:
I/System.out:错误:偏移量 120 处出现意外的 JSON 令牌:遇到未知密钥“模板类型”。在“Json {}”构建器中使用“ignoreUnknownKeys = true”来忽略未知键。JSON 输入:.....“名称”:“Nissan PathFinder”,“模板类型”:“”,“template_.....
我不想忽略未知的密钥,因为我实际上需要它。
Kotlin 协程和非阻塞 I/O 之间有什么关系?其中之一是否暗示着另一个?如果我使用阻塞 I/O 会发生什么?这对性能有何影响?
我正在尝试Ktor通过转换一些当前正在使用的现有项目Retrofit。
虽然我可以轻松地将请求转换为类似的内容:
client.get {
url("$BASE_URL/something/somepage/another")
}
Run Code Online (Sandbox Code Playgroud)
$BASE_URL每次都添加到所有路径似乎很乏味。在改造中,我们可以简单地执行以下操作:
Retrofit.Builder()
.baseUrl(BASE_URL)
.create(SomeServiceClass::class.java)
Run Code Online (Sandbox Code Playgroud)
我已经尝试使用defaultRequest和设置BASE_URL那里,但显然你只能设置url.host而不是整个basePath.
有没有办法在 中做同样的事情Ktor?或者如果没有,处理这个问题的最佳做法是什么?
ktor-client ×12
kotlin ×11
ktor ×11
android ×4
java ×1
kotlin-multiplatform-mobile ×1
nonblocking ×1
ssl ×1