{"id":583828,"date":"2025-07-17T15:48:58","date_gmt":"2025-07-17T14:48:58","guid":{"rendered":"https:\/\/blog.jetbrains.com\/?post_type=kotlin&#038;p=583828"},"modified":"2025-07-17T15:49:03","modified_gmt":"2025-07-17T14:49:03","slug":"ktor-3-2-0-is-now-available-2","status":"publish","type":"kotlin","link":"https:\/\/blog.jetbrains.com\/zh-hans\/kotlin\/2025\/07\/ktor-3-2-0-is-now-available-2","title":{"rendered":"Ktor 3.2.2 Is Now Available"},"content":{"rendered":"\n<p>The Ktor 3.2.2 patch release brings a critical fix for Android D8 compatibility, along with some minor enhancements and bug fixes.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">? Get started<\/h2>\n\n\n\n<p>Ready to explore Ktor 3.2.2? Start building your next project today with our interactive project generator at <a href=\"https:\/\/kotl.in\/ixiien\" target=\"_blank\" rel=\"noopener\">start.ktor.io<\/a>. Your feedback and contributions are always welcome!<br><br>?<a href=\"https:\/\/ktor.io\/docs\/welcome.html\" target=\"_blank\" rel=\"noopener\"> Get Started With Ktor<\/a> | ? Join the Community on<a href=\"https:\/\/www.reddit.com\/r\/ktor\/\" target=\"_blank\" rel=\"noopener\"> Reddit<\/a> and<a href=\"https:\/\/surveys.jetbrains.com\/s3\/kotlin-slack-sign-up?_gl=1*1wxglsg*_gcl_au*MTE4MjgxMTg3Mi4xNzM2MjY0ODgy*_ga*MTYyODczMDg5NS4xNzAyMDQyMTMx*_ga_9J976DJZ68*MTczODY3Mjg3Ny4xOTguMS4xNzM4NjczNDI2LjM2LjAuMA..\" target=\"_blank\" rel=\"noopener\"> Slack<\/a><\/p>\n\n\n\n<div class=\"buttons\">\n        <div class=\"buttons__row\">\n            <a class=\"ek-link jb-download-button\" title=\"Get Started With Ktor\" href=\"https:\/\/ktor.io\/docs\/welcome.html\" target=\"_blank\" rel=\"noopener\" data-test=\"blog-article-cta\" data-cl=\"true\">Get Started With Ktor<\/a>\n         <\/div>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Fixed Android D8 compatibility<\/h2>\n\n\n\n<p><a href=\"https:\/\/blog.jetbrains.com\/kotlin\/2025\/06\/ktor-3-2-0-is-now-available\/\">Ktor 3.2.0<\/a> introduced a compatibility issue for Android&#8217;s D8 by using Kotlin&#8217;s <a href=\"https:\/\/kotlinlang.org\/spec\/syntax-and-grammar.html#identifiers\" target=\"_blank\" rel=\"noopener\">backticked identifiers<\/a>, which are commonly used in testing and allow for non-alphanumeric characters in Kotlin names. Android&#8217;s D8 tool, which converts bytecode to DEX\u00a0 (Dalvik executable) format, only supports these backticked identifiers on Android 10 (API level 30) and newer.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"kotlin\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">@Test\nfun `hello world returns 200`() = testApplication {\n    routing {\n        get(\"\/hello\") {\n            call.respondText(\"Hello World!\")\n        }\n     }\n     val response = client.get(\"\/hello\")\n     assertEquals(HttpStatusCode.OK, response.status)\n}<\/pre>\n\n\n\n<p>This regression is fixed in Ktor 3.2.2. To prevent this from happening again, we&#8217;ve added new checks to our testing infrastructure. These tests continuously verify Ktor&#8217;s compatibility with essential Android tools, including D8 and ProGuard, ensuring new features don&#8217;t break support for older Android versions. More details can be found on <a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-8583\" target=\"_blank\" rel=\"noopener\">YouTrack<\/a> and on <a href=\"https:\/\/github.com\/ktorio\/ktor\/pull\/4933\" target=\"_blank\" rel=\"noopener\">GitHub<\/a>.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Minor bug fixes and enhancements<\/h2>\n\n\n\n<h3 class=\"wp-block-heading\">Improvements<\/h3>\n\n\n\n<ul>\n<li>Thymeleaf: The template model now accepts null values (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-8559\" target=\"_blank\" rel=\"noopener\">KTOR-8559<\/a>).<\/li>\n\n\n\n<li><code>javadoc<\/code> now published as a Maven artifact (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-3962\" target=\"_blank\" rel=\"noopener\">KTOR-3962<\/a>).<\/li>\n\n\n\n<li>Netty: An invalid hex byte with a malformed query string now returns the expected 400 Bad Request error instead of a 500 Internal Server Error.&nbsp; (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-2934\" target=\"_blank\" rel=\"noopener\">KTOR-2934<\/a>).<\/li>\n<\/ul>\n\n\n\n<p><br>It automatically closes AutoCloseable instances or allows to configure your own cleanup handlers. When the server receives a stop command, the HikariDataSource will close automatically, and then the custom cleanup handler for <strong>Database<\/strong> will be executed.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Regression fixes<\/h3>\n\n\n\n<ul>\n<li>A <em>Space characters in SimpleName<\/em> error is no longer triggered when executing an R8 mergeExtDex task with 3.2.0 (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-8583\" target=\"_blank\" rel=\"noopener\">KTOR-8583<\/a>).<\/li>\n\n\n\n<li>A potential race condition no longer occurs in socket.awaitClosed (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-8618\" target=\"_blank\" rel=\"noopener\">KTOR-8618<\/a>).<\/li>\n\n\n\n<li>The module parameter type Application.() -&gt; kotlin.Unit is now supported (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-8602\" target=\"_blank\" rel=\"noopener\">KTOR-8602<\/a>).<\/li>\n\n\n\n<li>Collecting flow in a Ktor route no longer results in a <em>Flow invariant is violated<\/em> error (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-8606\" target=\"_blank\" rel=\"noopener\">KTOR-8606<\/a>).<\/li>\n<\/ul>\n\n\n\n<h3 class=\"wp-block-heading\">Bug fixes<\/h3>\n\n\n\n<ul>\n<li>ForwardedHeaders: The plugin now handles parameters case-insensitively, as expected (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-8622\" target=\"_blank\" rel=\"noopener\">KTOR-8622<\/a>).<\/li>\n\n\n\n<li>OkHttp: java.net.ProtocolException no longer occurs when sending MultiPartFormDataContent with onUpload (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-6790\" target=\"_blank\" rel=\"noopener\">KTOR-6790<\/a>).<\/li>\n\n\n\n<li>The OAuth2 authentication provider no longer breaks form-urlencoded POST requests when receiving the request body (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-4420\" target=\"_blank\" rel=\"noopener\">KTOR-4420<\/a>).<\/li>\n\n\n\n<li>The <em>You can learn more from Content negotiation and serialization<\/em> KDoc link for io.ktor.server.plugins.contentnegotiation.ContentNegotiation now leads to the correct page (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-8597\" target=\"_blank\" rel=\"noopener\">KTOR-8597<\/a>).<\/li>\n\n\n\n<li>Ktor no longer fails to boot with the default jvminline argument (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-8608\" target=\"_blank\" rel=\"noopener\">KTOR-8608<\/a>).<\/li>\n\n\n\n<li>The ResponseSent hook handler of the plugin installed into a route is now executed as expected when an exception is thrown from the route (<a href=\"https:\/\/youtrack.jetbrains.com\/issue\/KTOR-6794\" target=\"_blank\" rel=\"noopener\">KTOR-6794<\/a>).<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>? <\/strong>Thank you!<\/h2>\n\n\n\n<p>We want to thank<a href=\"https:\/\/github.com\/MarcusDunn\" target=\"_blank\" rel=\"noopener\"> <\/a>everyone in the community for your support and feedback, as well as for reporting issues.<\/p>\n\n\n\n<p>Start building your next project at<a href=\"https:\/\/kotl.in\/ixiien\" target=\"_blank\" rel=\"noopener\"> start.ktor.io<\/a>. Your suggestions and contributions are always welcome!<\/p>\n\n\n\n<p>?<a href=\"https:\/\/ktor.io\/docs\/welcome.html\" target=\"_blank\" rel=\"noopener\"> Get Started With Ktor<\/a> | ? Join the Community on<a href=\"https:\/\/www.reddit.com\/r\/ktor\/\" target=\"_blank\" rel=\"noopener\"> Reddit<\/a> and<a href=\"https:\/\/surveys.jetbrains.com\/s3\/kotlin-slack-sign-up?_gl=1*1wxglsg*_gcl_au*MTE4MjgxMTg3Mi4xNzM2MjY0ODgy*_ga*MTYyODczMDg5NS4xNzAyMDQyMTMx*_ga_9J976DJZ68*MTczODY3Mjg3Ny4xOTguMS4xNzM4NjczNDI2LjM2LjAuMA..\" target=\"_blank\" rel=\"noopener\"> Slack<\/a><\/p>\n","protected":false},"author":1566,"featured_media":583969,"comment_status":"closed","ping_status":"closed","template":"","categories":[4897,89,907],"tags":[4292,76,477],"cross-post-tag":[6634],"acf":[],"_links":{"self":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/kotlin\/583828"}],"collection":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/kotlin"}],"about":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/types\/kotlin"}],"author":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/users\/1566"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/comments?post=583828"}],"version-history":[{"count":8,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/kotlin\/583828\/revisions"}],"predecessor-version":[{"id":676135,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/kotlin\/583828\/revisions\/676135"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media\/583969"}],"wp:attachment":[{"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/media?parent=583828"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/categories?post=583828"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/tags?post=583828"},{"taxonomy":"cross-post-tag","embeddable":true,"href":"https:\/\/blog.jetbrains.com\/zh-hans\/wp-json\/wp\/v2\/cross-post-tag?post=583828"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}