Ktor เป็น HTTP Client และ Server Framework แบบอะซิงโครนัสสำหรับ Kotlin ที่รองรับการพัฒนาข้ามแพลตฟอร์ม ไลบรารีถูกสร้างบน coroutines ของ Kotlin และทำงานบน JVM, iOS, Android, JS และ Native ตามข้อมูลจาก คลังเก็บ Ktor บน GitHub โปรเจกต์กำลังถูกพัฒนาอย่างต่อเนื่องโดย ทีม JetBrains Ktor นำเสนอสถาปัตยกรรมแบบโมดูลาร์พร้อมระบบปลั๊กอินสำหรับการกำหนดค่าการเชื่อมต่อ HTTP ที่ยืดหยุ่น
ประเด็นสำคัญ
Ktor คือเฟรมเวิร์กสำหรับสร้าง HTTP Client และ Server ในภาษา Kotlin พัฒนาโดย JetBrains แตกต่างจากไลบรารีแบบดั้งเดิม Ktor ถูกออกแบบตั้งแต่เริ่มต้นสำหรับการพัฒนาข้ามแพลตฟอร์มและทำงานบนทุกแพลตฟอร์มที่ Kotlin รองรับ
Ktor ใช้แนวทาง middleware ที่ได้รับแรงบันดาลใจจากสถาปัตยกรรมของ Kodein และ Express.js แต่ละคำขอผ่านไปตาม pipeline ของฟังก์ชัน handler ที่สามารถปรับเปลี่ยนคำขอและการตอบสนองได้ สิ่งนี้ให้ความยืดหยุ่นที่ไม่มีในไลบรารีที่มีสถาปัตยกรรมแบบตายตัวที่ใช้คำอธิบายประกอบ
เวอร์ชันปัจจุบัน Ktor 3.0 รวมถึง การรองรับ Kotlin 2.0, คอมไพเลอร์ K2 และเอ็นจิน CIO (Coroutine I/O) ใหม่ที่มีประสิทธิภาพดีขึ้น ไลบรารีเผยแพร่ภายใต้ใบอนุญาต Apache 2.0 และพร้อมใช้งานสำหรับการใช้งานเชิงพาณิชย์โดยไม่มีข้อจำกัด
ฝั่งไคลเอ็นต์ของ Ktor สร้างขึ้นบน coroutines ของ Kotlin อย่างสมบูรณ์ ทำให้การดำเนินการคำขอแบบอะซิงโครนัสมีประสิทธิภาพโดยไม่ต้องบล็อกเธรด ฝั่งเซิร์ฟเวอร์ช่วยให้สามารถสร้าง HTTP Server ด้วยการกำหนดเส้นทาง การจัดการคำขอ และการเชื่อมต่อ WebSocket
Ktor ใช้สถาปัตยกรรม ปลั๊กอิน: ฟังก์ชั่นเพิ่มเติมทั้งหมด — logging, serialization, การตรวจสอบสิทธิ์ — เชื่อมต่อผ่านปลั๊กอิน สิ่งนี้ทำให้ไลบรารีเป็นโมดูลาร์และช่วยให้สามารถเชื่อมต่อเฉพาะส่วนประกอบที่จำเป็น ลดขนาดของแอปพลิเคชันสุดท้าย
ต้องขอบคุณ API ที่เป็นหนึ่งเดียวบนทุกแพลตฟอร์ม นักพัฒนาไม่จำเป็นต้องเรียนรู้ HTTP Client ที่แตกต่างกันสำหรับ iOS และ Android ในโปรเจกต์ข้ามแพลตฟอร์ม โค้ดของเลเยอร์เครือข่ายถูกแชร์อย่างสมบูรณ์ และการใช้งานเฉพาะแพลตฟอร์มถูกซ่อนอยู่เบื้องหลังเอ็นจิน HttpClient สิ่งนี้ช่วยลดเวลาในการพัฒนาและลดจำนวนข้อผิดพลาดที่เกี่ยวข้องกับความแตกต่างของแพลตฟอร์ม
Ktor มีชุดคุณสมบัติที่ทำให้เป็นตัวเลือกที่น่าสนใจสำหรับโปรเจกต์ Kotlin สมัยใหม่ โดยเฉพาะโปรเจกต์ข้ามแพลตฟอร์ม
Ktor ทำงานบน JVM, Android, iOS, macOS, Windows, Linux, JavaScript และ Wasm โค้ด HTTP Client เดียวกันทำงานบนทุกแพลตฟอร์มโดยไม่ต้องเปลี่ยนแปลง นี่คือข้อได้เปรียบหลักเหนือไลบรารีที่ผูกติดกับ OkHttp หรือ URLSession
Coroutines ใน Kotlin ให้ความสามารถแบบอะซิงโครนัสตามธรรมชาติโดยไม่ต้องใช้ callback แต่ละคำขอเป็นฟังก์ชัน suspend ที่สามารถเรียกจาก coroutine ใดก็ได้ Ktor รองรับการสตรีมการตอบสนองผ่าน Flow ซึ่งสะดวกสำหรับการเชื่อมต่อที่ยาวนานและ WebSocket
ปลั๊กอินของ Ktor เชื่อมต่อผ่านบล็อก install และกำหนดค่าแยกต่างหาก ปลั๊กอินหลัก: ContentNegotiation สำหรับ serialization, Logging สำหรับการบันทึก, Auth สำหรับการตรวจสอบสิทธิ์ และ WebSockets สำหรับการสื่อสารสองทาง แต่ละปลั๊กอินสามารถเปิดหรือปิดใช้งานได้อย่างอิสระ
การจัดการข้อผิดพลาดใน Ktor ขึ้นอยู่กับข้อยกเว้น คลาส ClientRequestException ถูกโยนสำหรับรหัส 4xx, ServerResponseException สำหรับ 5xx และ IOException สำหรับความล้มเหลวของเครือข่าย การหมดเวลาถูกกำหนดค่าผ่านปลั๊กอิน HttpTimeout ซึ่งกำหนดเวลารอสำหรับการเชื่อมต่อ การอ่าน และการเขียน สำหรับการลองใหม่ ใช้ปลั๊กอิน Retry พร้อมการตั้งค่าจำนวนครั้งและความล่าช้า
Ktor ใช้สถาปัตยกรรม pipeline โดยแต่ละคำขอจะผ่านห่วงโซ่ของ handler ไคลเอ็นต์สร้างการกำหนดค่า HttpClient ด้วยปลั๊กอินที่ติดตั้ง และการเรียก get หรือ post แต่ละครั้งจะผ่านปลั๊กอินตามลำดับที่เชื่อมต่อ
ออบเจ็กต์ HttpClient ถูกสร้างขึ้นด้วยเอ็นจินเฉพาะแพลตฟอร์ม: CIO สำหรับ JVM และ Android, Darwin สำหรับ iOS และ macOS, OkHttp สำหรับความเข้ากันได้กับ Android, Js สำหรับเบราว์เซอร์ สามารถเลือกเอ็นจินอย่างชัดเจนหรือปล่อยให้เลือกอัตโนมัติ แต่ละคำขอจะคืน HttpResponse ที่มีเนื้อหาการตอบสนอง ส่วนหัว และสถานะ
val client = HttpClient(CIO) {
install(ContentNegotiation) {
json(Json {
ignoreUnknownKeys = true
})
}
}
suspend fun fetchUsers(): List<User> {
return client.get("https://api.example.com/users").body()
}
การติดตั้ง Ktor ทำผ่าน Gradle หรือ Maven สำหรับโปรเจกต์ข้ามแพลตฟอร์ม dependencies ถูกระบุใน sourceSets สำหรับแต่ละเป้าหมาย Ktor เผยแพร่ผ่าน Maven Central
ใน build.gradle.kts เพิ่ม dependency ktor-client-core สำหรับโค้ดทั่วไปและเอ็นจินสำหรับแพลตฟอร์มเฉพาะ เวอร์ชัน Ktor ถูกกำหนดผ่านตัวแปรใน gradle.properties Ktor 3.x ต้องการ Kotlin 2.0+ และรองรับคอมไพเลอร์ K2
val ktorVersion = "3.0.3"
dependencies {
implementation("io.ktor:ktor-client-core:$ktorVersion")
implementation("io.ktor:ktor-client-cio:$ktorVersion")
implementation("io.ktor:ktor-client-content-negotiation:$ktorVersion")
implementation("io.ktor:ktor-serialization-kotlinx-json:$ktorVersion")
implementation("io.ktor:ktor-client-logging:$ktorVersion")
}
สำหรับ iOS ใช้เอ็นจิน Darwin ซึ่งครอบ URLSession ดั้งเดิม ใน Kotlin Multiplatform สิ่งนี้ให้ประสิทธิภาพสูงสุดและการรวมกับกลไกแคชระบบของ iOS เอ็นจินถูกเพิ่มเป็น dependency แยกต่างหากใน iOS sourceSet
คุณสมบัติที่สำคัญของ Ktor คือ การรองรับรูปแบบ serialization ที่แตกต่างกันผ่าน ContentNegotiation นอกเหนือจาก JSON แล้ว ปลั๊กอินยังรองรับ Protobuf, CBOR, XML และรูปแบบที่กำหนดเอง สำหรับ serialization ใช้ไลบรารี kotlinx.serialization หรือ Jackson และนักพัฒนาสามารถสลับระหว่างพวกเขาได้โดยไม่ต้องเปลี่ยนโค้ดคำขอ
ตัวอย่างด้านล่างแสดงสถานการณ์ทั่วไปของการทำงานกับ Ktor client: คำขอ GET พื้นฐาน การส่งข้อมูล และการทำงานกับโค้ดข้ามแพลตฟอร์ม
คำขอ GET ง่ายๆ ที่มีการ deserialize การตอบสนองเป็น data class โดยอัตโนมัติ Ktor ใช้ปลั๊กอิน ContentNegotiation กับ kotlinx.serialization เพื่อแปลง JSON เป็นออบเจ็กต์ โค้ดสั้นและปลอดภัยของประเภท
@Serializable
data class Post(
val id: Int,
val title: String,
val body: String
)
suspend fun getPosts(): List<Post> {
val response = client.get("https://jsonplaceholder.typicode.com/posts")
return response.body()
}
คำขอ POST ใน Ktor ส่ง data class เป็นเนื้อหา JSON ผ่านเมธอด post พร้อม contentType และ setBody ปลั๊กอิน ContentNegotiation จะ serialize ออบเจ็กต์เป็นสตริง JSON โดยอัตโนมัติ การตอบสนองสามารถประมวลผลแบบซิงโครนัสหรืออะซิงโครนัส
suspend fun createPost(): Post {
val newPost = Post(
id = 0,
title = "โพสต์ใหม่",
body = "เนื้อหาโพสต์"
)
val response = client.post("https://jsonplaceholder.typicode.com/posts") {
contentType(ContentType.Application.Json)
setBody(newPost)
}
return response.body()
}
เมธอด submitFormWithBinaryData ใน Ktor อนุญาตให้ส่งไฟล์และฟอร์มในรูปแบบ multipart Ktor จะแบ่งข้อมูลเป็นส่วนๆ และเพิ่มส่วนหัวโดยอัตโนมัติ เพื่อติดตามความคืบหน้า ใช้ onUpload ซึ่งรับไบต์ของข้อมูลที่ส่ง
suspend fun uploadFile(fileBytes: ByteArray) {
client.submitFormWithBinaryData(
url = "https://api.example.com/upload",
formData = formData {
append("file", fileBytes, Headers.build {
append(HttpHeaders.ContentType, "image/png")
append(HttpHeaders.ContentDisposition, "filename=\"photo.png\"")
})
}
)
}
การเลือกระหว่าง Ktor และ Retrofit ขึ้นอยู่กับสถาปัตยกรรมของโปรเจกต์และความต้องการข้ามแพลตฟอร์ม Retrofit ยังคงเป็นมาตรฐานสำหรับโปรเจกต์ที่ใช้ Android เท่านั้น ในขณะที่ Ktor เป็นตัวเลือกที่ดีที่สุดสำหรับ Kotlin Multiplatform
Ktor ยังมี การรองรับในตัวสำหรับ WebSocket และ SSE (Server-Sent Events) ทำให้สะดวกสำหรับแอปพลิเคชันแบบเรียลไทม์ Retrofit ไม่รองรับ WebSocket โดยตรง — จำเป็นต้องใช้ไลบรารี OkHttp WebSocket แยกต่างหาก Ktor ยังกำหนดค่าสำหรับสภาพแวดล้อมที่แตกต่างกันได้ง่ายกว่าด้วยระบบปลั๊กอินที่ปลั๊กอินแต่ละตัวรับผิดชอบหนึ่งฟังก์ชัน
ปลั๊กอิน Auth ใน Ktor รองรับการตรวจสอบสิทธิ์พื้นฐาน, Bearer token, Digest และ OAuth2 การกำหนดค่าการตรวจสอบสิทธิ์ทำแบบประกาศ: นักพัฒนาระบุผู้ให้บริการ แหล่งที่มาของ token และขอบเขต Ktor จะเพิ่มส่วนหัวการตรวจสอบสิทธิ์ให้กับคำขอโดยอัตโนมัติและสามารถรีเฟรช token เมื่อหมดอายุ
หากโปรเจกต์ใช้ Kotlin Multiplatform ด้วยโค้ดที่แชร์ระหว่าง iOS และ Android Ktor เป็นตัวเลือกเดียวที่ทำงานบนทั้งสองแพลตฟอร์มโดยไม่มีเลเยอร์เพิ่มเติม Retrofit ผูกติดกับ OkHttp และ JVM อย่างแน่นหนา ทำให้ไม่เหมาะสมสำหรับ iOS
สำหรับโปรเจกต์ ที่ใช้ Android เท่านั้น Retrofit มี API ที่โตเต็มที่กว่า ตัวแปลงและตัวสกัดกั้น OkHttp จำนวนมากกว่า Ktor ก็ทำงานในสถานการณ์นี้เช่นกัน แต่ระบบนิเวศปลั๊กอินของมันกว้างขวางน้อยกว่า ไลบรารีทั้งสองรองรับ coroutines และให้ประสิทธิภาพที่เทียบเคียงได้
| เกณฑ์ | Ktor | Retrofit |
|---|---|---|
| ข้ามแพลตฟอร์ม | iOS, Android, JVM, JS, Native | เฉพาะ JVM และ Android |
| เอ็นจิน HTTP | CIO, Darwin, OkHttp, Js | OkHttp |
| ตัวแปลง | kotlinx.serialization, Jackson | Gson, Moshi, Jackson, Protobuf |
| สถาปัตยกรรม | Pipeline พร้อมปลั๊กอิน | คำอธิบายประกอบพร้อมการสร้างโค้ด |
| ผู้พัฒนา | JetBrains | Square |
คำถามที่พบบ่อย
Ktor — HTTP Client ข้ามแพลตฟอร์มบน coroutines จาก JetBrains Retrofit — ไลบรารี Android จาก Square ที่อิงจาก OkHttp Ktor ทำงานบน iOS, Android, JS และ Native ในขณะที่ Retrofit ทำงานบน JVM เท่านั้น
ได้, Ktor รองรับ iOS ผ่านเอ็นจิน Darwin ที่ใช้ URLSession ดั้งเดิม สิ่งนี้รับประกันประสิทธิภาพสูงสุดและการทำงานที่ถูกต้องกับแคชระบบ iOS โค้ดไคลเอ็นต์ยังคงถูกแชร์ระหว่างแพลตฟอร์ม
Ktor รองรับเอ็นจิน: CIO (JVM/Android), Darwin (iOS/macOS), OkHttp (Android), Js (เบราว์เซอร์), Jetty, Netty, Tomcat (เซิร์ฟเวอร์) สามารถเลือกเอ็นจินอย่างชัดเจนหรือปล่อยให้เลือกอัตโนมัติตามค่าเริ่มต้น
ได้, Ktor มีการรองรับ WebSocket ในตัวทั้งฝั่งไคลเอ็นต์และเซิร์ฟเวอร์ สำหรับไคลเอ็นต์ ใช้ปลั๊กอิน WebSockets ซึ่งช่วยให้สร้างการเชื่อมต่อสองทางและแลกเปลี่ยนข้อความแบบเรียลไทม์
ข้อผิดพลาดถูกจัดการผ่าน try-catch รอบการเรียก suspend Ktor โยน ClientRequestException สำหรับ 4xx, ServerResponseException สำหรับ 5xx และ IOException สำหรับข้อผิดพลาดเครือข่าย แนะนำให้ใช้ประเภท Result สำหรับการรวมเป็นหนึ่ง
สรุป
เราจะพัฒนาแอปพลิเคชันบนมือถือแบบครบวงจร
IT Sectr สร้างแอปพลิเคชัน iOS และ Android สำหรับสตาร์ทอัพและธุรกิจตั้งแต่ปี 2017 เราจะให้คำแนะนำและเสนอวิธีแก้ปัญหาที่ดีที่สุดแก่คุณ
อ่านเพิ่มเติม