标签: ktor-client

在 Ktor 客户端中重新触发 loadTokens 的正确方法

在我的移动应用程序中,我有一个单例 Ktor HttpClient,其不记名身份验证配置如下:

\n
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}\n
Run Code Online (Sandbox Code Playgroud)\n

现在考虑以下流程:

\n
    \n
  1. 用户打开应用程序,而 my 中存储的令牌tokenStorage无效。
  2. \n
  3. 从中加载HttpClient令牌tokenStorage,请求失败并返回 401。
  4. \n
  5. 尝试HttpClient执行刷新,但也失败,因为刷新令牌无效。
  6. \n
  7. 用户被重定向到登录页面,登录,新的有效令牌存储在tokenStorage.
  8. \n
  9. 现在,用户可以从应用程序重试第 2-3 点中失败的呼叫。然而,这将永远失败,直到应用程序关闭,因为它HttpClient不再尝试调用loadTokens。确实,从源代码来看,loadTokens只被调用一次,然后就不会再被调用。
  10. \n
\n

我找到了解决该问题的几种方法。

\n

第一个是手动BearerAuthProviderHttpClient自己清除令牌,如以下代码片段所示,但这似乎是一种黑客解决方法:

\n
httpClient.plugin(Auth).providers\n    .filterIsInstance<BearerAuthProvider>()\n    .first().clearToken()\n
Run Code Online (Sandbox Code Playgroud)\n

tokenStorage另一种方法是从 my in手动加载当前令牌refreshToken并忽略传入的内容this@refreshTokens.oldTokens …

kotlin ktor ktor-client

14
推荐指数
0
解决办法
1521
查看次数

在 Ktor 中,如何将 InputStream 流式传输到 HttpClient 请求的主体中?

我正在使用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)

如果我遗漏了任何相关信息,请告诉我,

谢谢!

kotlin ktor ktor-client

8
推荐指数
2
解决办法
6331
查看次数

kotlinx.serialization.SerializationException:找不到类“MultiPartFormDataContent”的序列化器

我正在尝试上传多个文件。

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

5
推荐指数
1
解决办法
3698
查看次数

如何禁用 Ktor 客户端 SSL 验证?

我正在尝试连接到一个具有来自内部测试环境的自签名证书的服务,该证书仅在原型设计期间存在。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)

在这种情况下如何禁用证书验证?

ssl kotlin ktor ktor-client

5
推荐指数
2
解决办法
5683
查看次数

Java 或 Kotlin 上下文中的 .api 文件是什么

当我发现这个文件时,我一直在 github 上查看 Ktor-client 源代码,试图在做出贡献之前理解它。我看到 java 语法,但我不明白为什么它有扩展名 (.api),以及它的用途。任何参考链接的答案将不胜感激。

java kotlin ktor-client

5
推荐指数
1
解决办法
638
查看次数

解析 ktor HTTPClient 中的错误正文

我有一个 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)

我在这里的查询是我不能够访问响应误差身体任一validateResponsehandleResponseException。有没有办法可以捕获并解析它以获取服务器发送的实际错误?

kotlin ktor kotlin-multiplatform ktor-client

4
推荐指数
1
解决办法
2846
查看次数

Ktor 客户端身份验证功能不发送授权标头

我试图在 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 ktor kotlin-multiplatform ktor-client

3
推荐指数
1
解决办法
2320
查看次数

无法在 Android Studio 中将 io.ktor 导入到 KMM 的公共模块

所以我是 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

3
推荐指数
1
解决办法
510
查看次数

如何清除 Android 版 Ktor 客户端中的不记名令牌

我正在将 Android 版 Ktor 客户端与插件一起使用:io.ktor:ktor-client-auth:1.6.4当前的实现与此代码片段类似。

现在我想在单击按钮后删除令牌时实现“注销”功能,问题是......如何实现?

android kotlin ktor ktor-client

3
推荐指数
1
解决办法
1413
查看次数

使用带有连字符的 @SerializedName 不起作用

我正在尝试将此 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_.....

我不想忽略未知的密钥,因为我实际上需要它。

android kotlin json-serialization ktor ktor-client

3
推荐指数
1
解决办法
1016
查看次数

非阻塞 I/O 和 Kotlin 协程之间有什么关系?

Kotlin 协程和非阻塞 I/O 之间有什么关系?其中之一是否暗示着另一个?如果我使用阻塞 I/O 会发生什么?这对性能有何影响?

nonblocking kotlin ktor kotlin-coroutines ktor-client

3
推荐指数
1
解决办法
2080
查看次数

如何在 Ktor 中设置类似于 Retrofit 的`Retrofit.Builder().baseUrl(baseUrl) 的 basePath?

我正在尝试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?或者如果没有,处理这个问题的最佳做法是什么?

android kotlin ktor kotlin-multiplatform ktor-client

0
推荐指数
2
解决办法
888
查看次数