Ktor возвращает 415 с конечных точек, где receive () используется с ContentNegotiation

У меня есть классы параметров с аннотацией @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")
    }
}

Если я провожу трассировку, я вижу, что мой маршрут совпадает, но он не может получить параметры. Должна ли эта установка json() работать, когда я выполняю десериализацию из таких параметров URL-адреса?


person Adam Arold    schedule 20.07.2020    source источник


Ответы (1)


Во-первых, функция ContentNegotiation работает только для получения настраиваемых объектов из полезных данных запросов POST, PUT и PATCH:

Запросы POST, PUT и PATCH имеют связанное тело запроса (полезную нагрузку). Эта полезная нагрузка обычно закодирована. Чтобы получить настраиваемые объекты из полезной нагрузки, вы должны использовать ContentNegotiation особенность. Это полезно, например, для получения и отправки полезных данных JSON в REST API. При получении Content-Type запроса будет использоваться, чтобы определить, какой ContentConverter будет использоваться для обработки этого запроса.

Во-вторых, из коробки доступны три ContentConverter: GsonConverter, JacksonConverter и SerializationConverter. У каждого из этих преобразователей есть собственная функция конфигурации: gson, jackson и serialization соответственно. Вы используете функцию конфигурации json, которая, скорее всего, не подходит для конфигурации ContentNegotiation.

Чтобы решить вашу проблему, вы можете получить доступ к параметрам URL, указав на них call.parameters и вручную создать ShowPostURL объект. Затем при необходимости сериализуйте его с помощью kotlinx.serialization framework.

Кроме того, вы можете написать свой собственный ContentConverter для реализации настраиваемой логики. для получения типизированных объектов.

person Aleksei Tirman    schedule 21.07.2020
comment
Я использую json, потому что об этом говорится в официальной документации. Я обсуждал это на Kotlin Slack, и парень из JetBrains сказал, что эта функция еще не поддерживается, вы не можете десериализовать объекты из URL-адресов вообще. - person Adam Arold; 23.07.2020