Skip to content

Commit

Permalink
Upgrade Ktor
Browse files Browse the repository at this point in the history
  • Loading branch information
ILIYANGERMANOV committed Nov 25, 2024
1 parent 9313dc2 commit 17988b0
Show file tree
Hide file tree
Showing 9 changed files with 39 additions and 37 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,6 @@ common/build/
!gradle-wrapper.properties

# Ignore local.properties file typically used for Android SDK path
local.properties
local.properties

.kotlin
2 changes: 1 addition & 1 deletion gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ androidx-test-junit = "1.2.1"
arrow = "1.2.4"
junit = "4.13.2"
kotlin = "2.0.21"
ktor = "2.3.10"
ktor = "3.0.1"
ktor-client = "3.0.1"
logback = "1.5.12"
kotest = "5.9.1"
Expand Down
1 change: 0 additions & 1 deletion server/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,6 @@ dependencies {
implementation(libs.bundles.ktor.client.common)
implementation(libs.ktor.client.java)

testImplementation(libs.ktor.server.tests)
testImplementation(libs.ktor.server.test.host)
testImplementation(libs.kotlin.test.junit)
testImplementation(libs.bundles.test)
Expand Down
1 change: 0 additions & 1 deletion server/src/main/kotlin/ivy/learn/api/AnalyticsApi.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package ivy.learn.api

import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import ivy.learn.api.common.Api
Expand Down
6 changes: 3 additions & 3 deletions server/src/main/kotlin/ivy/learn/api/CoursesApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import arrow.core.raise.ensureNotNull
import io.ktor.server.routing.*
import ivy.data.source.model.CourseResponse
import ivy.learn.api.common.Api
import ivy.learn.api.common.endpoint
import ivy.learn.api.common.getEndpoint
import ivy.learn.api.common.model.ServerError.BadRequest
import ivy.learn.data.repository.CoursesRepository
import ivy.learn.data.repository.LessonsRepository
Expand All @@ -19,7 +19,7 @@ class CoursesApi(
}

private fun Routing.courseBy() {
get("/courses/{id}", endpoint { params ->
getEndpoint("/courses/{id}") { params ->
val courseId = params["id"]?.let(::CourseId)
ensureNotNull(courseId) { BadRequest("Course id is required.") }
val course = coursesRepository.fetchCourseById(courseId)
Expand All @@ -30,6 +30,6 @@ class CoursesApi(
course = course,
lessons = lessons
)
})
}
}
}
8 changes: 3 additions & 5 deletions server/src/main/kotlin/ivy/learn/api/LessonsApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@ package ivy.learn.api

import arrow.core.raise.ensureNotNull
import io.ktor.server.routing.*
import io.ktor.utils.io.*
import ivy.learn.api.common.Api
import ivy.learn.api.common.endpoint
import ivy.learn.api.common.getEndpoint
import ivy.learn.api.common.model.ServerError
import ivy.learn.api.common.model.ServerError.BadRequest
import ivy.learn.data.repository.LessonsRepository
Expand All @@ -19,15 +18,14 @@ class LessonsApi(
lessonById()
}

@KtorDsl
private fun Routing.lessonById() {
get("/lessons/{courseId}/{lessonId}", endpoint<Lesson> { params ->
getEndpoint<Lesson>("/lessons/{courseId}/{lessonId}") { params ->
val courseId = params["courseId"]?.let(::CourseId)
val lessonId = params["lessonId"]?.let(::LessonId)
ensureNotNull(courseId) { BadRequest("Course id is missing!") }
ensureNotNull(lessonId) { BadRequest("Lesson id is missing!") }
repository.fetchLesson(courseId, lessonId)
.mapLeft(ServerError::Unknown).bind()
})
}
}
}
6 changes: 3 additions & 3 deletions server/src/main/kotlin/ivy/learn/api/StatusApi.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,17 +2,17 @@ package ivy.learn.api

import io.ktor.server.routing.*
import ivy.learn.api.common.Api
import ivy.learn.api.common.endpoint
import ivy.learn.api.common.getEndpoint
import kotlinx.serialization.Serializable

class StatusApi : Api {
override fun Routing.endpoints() {
get("/hello", endpoint {
getEndpoint("/hello") {
HelloResponse(
message = "Hello, world!",
time = System.currentTimeMillis(),
)
})
}
}
}

Expand Down
8 changes: 3 additions & 5 deletions server/src/main/kotlin/ivy/learn/api/TopicsApi.kt
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
package ivy.learn.api

import io.ktor.server.routing.*
import io.ktor.utils.io.*
import ivy.data.source.model.TopicsResponse
import ivy.learn.api.common.Api
import ivy.learn.api.common.endpoint
import ivy.learn.api.common.getEndpoint
import ivy.learn.data.repository.CoursesRepository
import ivy.learn.data.repository.TopicsRepository

Expand All @@ -16,13 +15,12 @@ class TopicsApi(
topics()
}

@KtorDsl
private fun Routing.topics() {
get("/topics", endpoint {
getEndpoint("/topics") {
TopicsResponse(
topics = topicsRepository.fetchTopics(),
courses = coursesRepository.fetchCourses()
)
})
}
}
}
40 changes: 23 additions & 17 deletions server/src/main/kotlin/ivy/learn/api/common/ApiUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,32 @@ package ivy.learn.api.common
import arrow.core.raise.Raise
import arrow.core.raise.either
import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.response.*
import io.ktor.util.pipeline.*
import io.ktor.server.routing.*
import ivy.learn.api.common.model.ServerError
import ivy.learn.api.common.model.ServerErrorResponse

inline fun <reified T : Any> endpoint(
@IvyServerDsl
inline fun <reified T : Any> Routing.getEndpoint(
path: String,
crossinline handler: suspend Raise<ServerError>.(Parameters) -> T
): suspend PipelineContext<Unit, ApplicationCall>.(Unit) -> Unit = {
either {
handler(call.parameters)
}.onLeft { error ->
call.respond(
status = when (error) {
is ServerError.BadRequest -> HttpStatusCode.BadRequest
is ServerError.Unknown -> HttpStatusCode.InternalServerError
},
message = ServerErrorResponse(error.msg)
)
}.onRight { response ->
call.respond(HttpStatusCode.OK, response)
) {
get(path) {
either {
handler(call.parameters)
}.onLeft { error ->
call.respond(
status = when (error) {
is ServerError.BadRequest -> HttpStatusCode.BadRequest
is ServerError.Unknown -> HttpStatusCode.InternalServerError
},
message = ServerErrorResponse(error.msg)
)
}.onRight { response ->
call.respond(HttpStatusCode.OK, response)
}
}
}
}

@DslMarker
annotation class IvyServerDsl

0 comments on commit 17988b0

Please sign in to comment.