From 4431d95d6d3098562711f319e17f7651b018183c Mon Sep 17 00:00:00 2001 From: Rustam <rxsinukov@gmail.com> Date: Mon, 13 Feb 2023 05:40:07 +0100 Subject: [PATCH] KTOR-3799 Add charset only for text/* content types (#3370) --- .../tests/JsonContentNegotiationTest.kt | 22 +++++++++++++++++++ .../common/src/io/ktor/http/ContentTypes.kt | 2 +- .../io/ktor/tests/http/ContentTypeTest.kt | 15 +++++++++++++ 3 files changed, 38 insertions(+), 1 deletion(-) diff --git a/ktor-client/ktor-client-plugins/ktor-client-content-negotiation/ktor-client-content-negotiation-tests/jvm/src/io/ktor/client/plugins/contentnegotiation/tests/JsonContentNegotiationTest.kt b/ktor-client/ktor-client-plugins/ktor-client-content-negotiation/ktor-client-content-negotiation-tests/jvm/src/io/ktor/client/plugins/contentnegotiation/tests/JsonContentNegotiationTest.kt index a071673a4a7..771c3082dfc 100644 --- a/ktor-client/ktor-client-plugins/ktor-client-content-negotiation/ktor-client-content-negotiation-tests/jvm/src/io/ktor/client/plugins/contentnegotiation/tests/JsonContentNegotiationTest.kt +++ b/ktor-client/ktor-client-plugins/ktor-client-content-negotiation/ktor-client-content-negotiation-tests/jvm/src/io/ktor/client/plugins/contentnegotiation/tests/JsonContentNegotiationTest.kt @@ -209,4 +209,26 @@ abstract class JsonContentNegotiationTest(private val converter: ContentConverte assertEquals(null, response.body<Wrapper?>()) } } + + @Test + fun testNoCharsetIsAdded() = testApplication { + routing { + post("/") { + assertNull(call.request.contentType().charset()) + call.respond("OK") + } + } + + createClient { + install(io.ktor.client.plugins.contentnegotiation.ContentNegotiation) { + register(ContentType("application", "json-patch+json"), converter) + } + }.post("/") { + val data: Wrapper? = null + contentType(ContentType("application", "json-patch+json")) + setBody(data) + }.let { + assertEquals("OK", it.bodyAsText()) + } + } } diff --git a/ktor-http/common/src/io/ktor/http/ContentTypes.kt b/ktor-http/common/src/io/ktor/http/ContentTypes.kt index dea67b7fb8d..64319b165b6 100644 --- a/ktor-http/common/src/io/ktor/http/ContentTypes.kt +++ b/ktor-http/common/src/io/ktor/http/ContentTypes.kt @@ -286,7 +286,7 @@ public fun ContentType.withCharset(charset: Charset): ContentType = * if [ContentType] is not ignored */ public fun ContentType.withCharsetIfNeeded(charset: Charset): ContentType = - if (contentType.lowercase() == "application" && contentSubtype.lowercase() == "json") { + if (contentType.lowercase() != "text") { this } else { withParameter("charset", charset.name) diff --git a/ktor-http/common/test/io/ktor/tests/http/ContentTypeTest.kt b/ktor-http/common/test/io/ktor/tests/http/ContentTypeTest.kt index 5c04982e362..dc07c2082cc 100644 --- a/ktor-http/common/test/io/ktor/tests/http/ContentTypeTest.kt +++ b/ktor-http/common/test/io/ktor/tests/http/ContentTypeTest.kt @@ -5,6 +5,7 @@ package io.ktor.tests.http import io.ktor.http.* +import io.ktor.utils.io.charsets.Charsets import kotlin.test.* class ContentTypeTest { @@ -140,4 +141,18 @@ class ContentTypeTest { val content = ContentType.parse(contentType) assertEquals("text/html; charset=UTF-8", content.toString()) } + + @Test + fun testNoCharsetForNonText() { + assertNull(ContentType.Audio.MP4.withCharsetIfNeeded(Charsets.UTF_8).charset()) + assertNull(ContentType.Application.Json.withCharsetIfNeeded(Charsets.UTF_8).charset()) + assertNull(ContentType("application", "json-patch+json").withCharsetIfNeeded(Charsets.UTF_8).charset()) + } + + @Test + fun testCharsetForText() { + assertEquals(Charsets.UTF_8, ContentType.Text.Any.withCharsetIfNeeded(Charsets.UTF_8).charset()) + assertEquals(Charsets.UTF_8, ContentType.Text.Html.withCharsetIfNeeded(Charsets.UTF_8).charset()) + assertEquals(Charsets.UTF_8, ContentType("Text", "custom").withCharsetIfNeeded(Charsets.UTF_8).charset()) + } }