diff --git a/build.gradle.kts b/build.gradle.kts index f44520855349d1923749cf1c2977690d8813f734..281e9894d826f73a5d0dd590b648dd1038a8ebe0 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -1,5 +1,6 @@ val koin_version: String by project val kotlin_version: String by project +val ktor_version: String by project val logback_version: String by project val dynamo_version: String by project val dynamo_kt_version: String by project @@ -32,11 +33,12 @@ repositories { dependencies { // Ktor - implementation("io.ktor:ktor-server-core") - implementation("io.ktor:ktor-server-auth") - implementation("io.ktor:ktor-server-openapi") - implementation("io.ktor:ktor-server-config-yaml") - implementation("io.ktor:ktor-server-netty") + implementation("io.ktor:ktor-server-core:$ktor_version") + implementation("io.ktor:ktor-server-auth:$ktor_version") + implementation("io.ktor:ktor-server-openapi:$ktor_version") + implementation("io.ktor:ktor-server-config-yaml:$ktor_version") + implementation("io.ktor:ktor-server-netty:$ktor_version") + implementation("io.ktor:ktor-server-status-pages:$ktor_version") // Dependency injection implementation("io.insert-koin:koin-ktor:$koin_version") @@ -52,6 +54,7 @@ dependencies { implementation("software.amazon.awssdk:dynamodb:$dynamo_version") implementation("dev.andrewohara:dynamokt:$dynamo_kt_version") implementation("org.jetbrains.kotlinx:kotlinx-coroutines-reactive:$kotlin_reactive_version") + implementation("io.ktor:ktor-server-host-common:$ktor_version") // Tests testImplementation("io.ktor:ktor-server-test-host") diff --git a/src/main/kotlin/Application.kt b/src/main/kotlin/Application.kt index 024521d5c28f2bb85e1ec1f9f1bcc72669c7ae6c..8814813902a09373370f79376cad193b93780c8b 100644 --- a/src/main/kotlin/Application.kt +++ b/src/main/kotlin/Application.kt @@ -1,5 +1,6 @@ package betclic.test +import betclic.test.configuration.configureExceptionHandling import betclic.test.configuration.configureKoin import betclic.test.configuration.configureRouting import betclic.test.configuration.configureSerialization @@ -19,6 +20,7 @@ fun Application.module() { fun Application.configuration() { configureKoin() configureSerialization() + configureExceptionHandling() configureRouting() } diff --git a/src/main/kotlin/configuration/ExceptionConfiguration.kt b/src/main/kotlin/configuration/ExceptionConfiguration.kt new file mode 100644 index 0000000000000000000000000000000000000000..c2a6274ab1836336f8d08e574f5a7139205a1176 --- /dev/null +++ b/src/main/kotlin/configuration/ExceptionConfiguration.kt @@ -0,0 +1,31 @@ +package betclic.test.configuration + +import betclic.test.player.exceptions.AlreadyExistingPlayerException +import io.ktor.http.* +import io.ktor.server.application.* +import io.ktor.server.plugins.* +import io.ktor.server.plugins.statuspages.* +import io.ktor.server.response.* +import software.amazon.awssdk.services.dynamodb.model.DynamoDbException + +private const val SOMETHING_WENT_WRONG = "Something went wrong" + +fun Application.configureExceptionHandling() { + install(StatusPages) { + exception<Throwable> { call, cause -> + when (cause) { + is NotFoundException -> call.respond(HttpStatusCode.NotFound, cause.message ?: SOMETHING_WENT_WRONG) + is DynamoDbException -> call.respond( + HttpStatusCode.InternalServerError, + cause.message ?: "$SOMETHING_WENT_WRONG with DynamoDb" + ) + + is AlreadyExistingPlayerException -> call.respond( + HttpStatusCode.BadRequest, + cause.message ?: SOMETHING_WENT_WRONG + ) + } + call.respondText(text = "500: $cause", status = HttpStatusCode.InternalServerError) + } + } +} \ No newline at end of file diff --git a/src/main/kotlin/player/PlayerRoute.kt b/src/main/kotlin/player/PlayerRoute.kt index b52c4c3bec27f7cf348019b36793c8db71221e50..439e37b54e7b3cefdb34fa9040440d1d885a75e0 100644 --- a/src/main/kotlin/player/PlayerRoute.kt +++ b/src/main/kotlin/player/PlayerRoute.kt @@ -3,56 +3,35 @@ package betclic.test.player import betclic.test.player.dtos.PlayerCreationDTO import betclic.test.player.dtos.PlayerInfoDTO import betclic.test.player.dtos.PlayerUpdateDTO -import betclic.test.player.exceptions.AlreadyExistingPlayerException import io.ktor.http.* import io.ktor.server.application.* -import io.ktor.server.plugins.* import io.ktor.server.request.* import io.ktor.server.response.* import io.ktor.server.routing.* import org.koin.ktor.ext.inject -private const val SOMETHING_WENT_WRONG = "Something went wrong." - fun Routing.playerRoutes() { val playerService by inject<PlayerService>() // const route("/players") { post { val request = call.receive<PlayerCreationDTO>() - try { - call.respond(HttpStatusCode.Created, playerService.createNewPlayer(request)) - } catch (e: AlreadyExistingPlayerException) { - call.respond(status = HttpStatusCode.BadRequest, message = e.message ?: SOMETHING_WENT_WRONG) - } + call.respond(HttpStatusCode.Created, playerService.createNewPlayer(request)) } put { val request = call.receive<PlayerUpdateDTO>() - try { - call.respond(HttpStatusCode.OK, playerService.updatePlayer(request)) - } catch (e: NotFoundException) { - call.respond(status = HttpStatusCode.NotFound, message = e.message ?: SOMETHING_WENT_WRONG) - } - + call.respond(HttpStatusCode.OK, playerService.updatePlayer(request)) } get("/{pseudo}") { val pseudo = call.parameters["pseudo"] ?: return@get call.respond(HttpStatusCode.BadRequest) - try { - call.respond<Player>(playerService.findPlayerByPseudo(pseudo)) - } catch (e: NotFoundException) { - call.respond(status = HttpStatusCode.NotFound, message = e.message ?: SOMETHING_WENT_WRONG) - } + call.respond<Player>(playerService.findPlayerByPseudo(pseudo)) } get("/{pseudo}/info") { val pseudo = call.parameters["pseudo"] ?: return@get call.respond(HttpStatusCode.BadRequest) - try { - call.respond<PlayerInfoDTO>(playerService.getPlayerInfoByPseudo(pseudo)) - } catch (e: NotFoundException) { - call.respond(status = HttpStatusCode.NotFound, message = e.message ?: SOMETHING_WENT_WRONG) - } + call.respond<PlayerInfoDTO>(playerService.getPlayerInfoByPseudo(pseudo)) } get("/ranking") { diff --git a/src/main/kotlin/player/exceptions/AlreadyExistingException.kt b/src/main/kotlin/player/exceptions/AlreadyExistingException.kt index 4deded5743a854df69d28a0ac238d4125af152f8..f08bc6f8ade080cf260c6cdcb5f965ac3be1a51c 100644 --- a/src/main/kotlin/player/exceptions/AlreadyExistingException.kt +++ b/src/main/kotlin/player/exceptions/AlreadyExistingException.kt @@ -1,4 +1,4 @@ package betclic.test.player.exceptions class AlreadyExistingPlayerException(val pseudo: String) : - RuntimeException("$pseudo already exists. You still can update this player points") \ No newline at end of file + Exception("$pseudo already exists. You still can update this player points") \ No newline at end of file