Ktor 从与 ContentNegotiation 一起使用 receive() 的端点返回 415

Posted

技术标签:

【中文标题】Ktor 从与 ContentNegotiation 一起使用 receive() 的端点返回 415【英文标题】:Ktor returns 415 from endpoints where receive() is used with ContentNegotiation 【发布时间】:2020-11-09 20:39:51 【问题描述】:

我有带有@Searializable 注释的参数类:

@Serializable
data class ShowPostURL(
        val date: String,
        val titleSlug: String,
        override val redirectTo: String? = null
)

无论我做什么call.receive() 都不起作用。我收到 HTTP 415 错误,而 Ktor 没有记录任何内容。我也添加了序列化支持:

install(ContentNegotiation) 
    json()

我该如何解决这个问题?这就是我尝试使用它的方式:

accept(ContentType.Any) 
    get("/foo/date/titleSlug") 
        val input = call.receive(ShowPostURL::class)
        call.respondText("foo")
    

如果我进行跟踪,我可以看到我的路由匹配,但它无法接收参数。当我从这样的 url 参数反序列化时,这个 json() 设置是否应该工作?

【问题讨论】:

【参考方案1】:

首先,ContentNegotiation 功能仅适用于从 POSTPUTPATCH 请求的负载接收自定义对象:

POST、PUT 和 PATCH 请求具有关联的请求正文(有效负载)。该有效载荷通常是经过编码的。 为了从有效负载接收自定义对象,您必须使用ContentNegotiation 功能。例如,这对于在 REST API 中接收和发送 JSON 有效负载很有用。 接收时,将使用请求的Content-Type 来确定将使用哪个ContentConverter 来处理该请求

其次,有三个开箱即用的ContentConverter 可用: GsonConverter、JacksonConverter 和 SerializationConverter。 这些转换器中的每一个都有自己的配置功能:分别为gsonjacksonserialization。你使用json的配置函数,很可能不适合ContentNegotiation的配置。

要解决您的问题,您可以通过使用 call.parameters 引用 URL 参数并手动创建 ShowPostURL 对象来访问它们。然后根据需要使用kotlinx.serialization 框架对其进行序列化。

另外,您可以编写自己的ContentConverter 来实现receiving typed objects 的自定义逻辑。

【讨论】:

我使用json 因为官方文档是这么说的。我在 Kotlin Slack 上讨论过这个问题,一个 JetBrains 的人说它还不支持这个功能,你根本不能反序列化来自 url 的对象。

以上是关于Ktor 从与 ContentNegotiation 一起使用 receive() 的端点返回 415的主要内容,如果未能解决你的问题,请参考以下文章

KTor 站点无法访问

Ktor挖坑日记还在用Retrofit网络请求吗?试试Ktor吧

Ktor挖坑日记还在用Retrofit网络请求吗?试试Ktor吧

“未找到转换:类 io.ktor.utils.io.ByteChannelNative”错误使用 Ktor

重定向到 Ktor 中的绝对 URL

Ktor Websocket 功能与 ktor 中的 ContentNeogation 功能 (JSON / GSON)