Skip to content

Commit

Permalink
Update to Ktor 3.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
MrPowerGamerBR committed Oct 14, 2024
1 parent 38e2312 commit 6fd711d
Show file tree
Hide file tree
Showing 7 changed files with 134 additions and 29 deletions.
2 changes: 1 addition & 1 deletion backend/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ dependencies {
implementation("io.ktor:ktor-server-compression:${Versions.KTOR}")
implementation("io.ktor:ktor-server-caching-headers:${Versions.KTOR}")

implementation("ch.qos.logback:logback-classic:1.3.0-alpha11")
implementation("ch.qos.logback:logback-classic:1.5.10")
implementation("commons-codec:commons-codec:1.15")

// https://mvnrepository.com/artifact/org.jsoup/jsoup
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ import io.ktor.server.engine.*
import io.ktor.server.http.content.*
import io.ktor.server.plugins.cachingheaders.*
import io.ktor.server.plugins.compression.*
import io.ktor.server.plugins.cors.*
import io.ktor.server.routing.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.runBlocking
Expand Down Expand Up @@ -139,10 +138,6 @@ class GalleryOfDreamsBackend(val languageManager: LanguageManager) {
}

val server = embeddedServer(CIO, port = System.getenv("GALLERYOFDREAMS_WEBSERVER_PORT")?.toIntOrNull() ?: 8080) {
install(CORS) {
anyHost()
}

// Enables gzip and deflate compression
install(Compression)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package net.perfectdreams.galleryofdreams.backend.routes.api

import club.minnced.discord.webhook.send.AllowedMentions
import club.minnced.discord.webhook.send.WebhookMessageBuilder
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.utils.io.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.io.readByteArray
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import net.perfectdreams.dreamstorageservice.data.api.CreateImageLinkRequest
Expand Down Expand Up @@ -36,18 +39,35 @@ class PostArtistWithFanArtRoute(m: GalleryOfDreamsBackend) : RequiresAPIAuthenti
val (fanArtArtist, response) = withContext(Dispatchers.IO) {
// Receive the uploaded file
val multipart = call.receiveMultipart()
val parts = multipart.readAllParts()
val filePart = parts.first { it.name == "file" } as PartData.FileItem
val attributesPart = parts.first { it.name == "attributes" } as PartData.FormItem

val attributes = Json.decodeFromString<CreateArtistWithFanArtRequest>(attributesPart.value)
var attributesString: String? = null
var contentType: ContentType? = null
var fileToBeStored: ByteArray? = null

val fileToBeStored = filePart.streamProvider.invoke().readAllBytes()
val contentType = filePart.contentType ?: error("Missing Content-Type!")
multipart.forEachPart { part ->
when (part) {
is PartData.FormItem -> {
if (part.name == "file")
attributesString = part.value
}

is PartData.FileItem -> {
if (part.name == "file") {
contentType = part.contentType
fileToBeStored = part.provider().readRemaining().readByteArray()
}
}

else -> {}
}
part.dispose()
}

val attributes = Json.decodeFromString<CreateArtistWithFanArtRequest>(attributesString!!)

val uploadResult = m.dreamStorageServiceClient.uploadImage(
fileToBeStored,
contentType,
fileToBeStored!!,
contentType!!,
UploadImageRequest(false)
)

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package net.perfectdreams.galleryofdreams.backend.routes.api

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.http.content.*
import io.ktor.server.request.*
import io.ktor.utils.io.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import kotlinx.io.readByteArray
import net.perfectdreams.dreamstorageservice.data.api.CheckImageRequest
import net.perfectdreams.dreamstorageservice.data.api.ImageDoesNotExistResponse
import net.perfectdreams.dreamstorageservice.data.api.ImageExistsResponse
Expand All @@ -23,15 +26,33 @@ class PostCheckFanArtRoute(m: GalleryOfDreamsBackend) : RequiresAPIAuthenticatio
val response = withContext(Dispatchers.IO) {
// Receive the uploaded file
val multipart = call.receiveMultipart()
val parts = multipart.readAllParts()
val filePart = parts.first { it.name == "file" } as PartData.FileItem

val fileToBeStored = filePart.streamProvider.invoke().readAllBytes()
val contentType = filePart.contentType ?: error("Missing Content-Type!")
var attributesString: String? = null
var contentType: ContentType? = null
var fileToBeStored: ByteArray? = null

multipart.forEachPart { part ->
when (part) {
is PartData.FormItem -> {
if (part.name == "file")
attributesString = part.value
}

is PartData.FileItem -> {
if (part.name == "file") {
contentType = part.contentType
fileToBeStored = part.provider().readRemaining().readByteArray()
}
}

else -> {}
}
part.dispose()
}

val checkResult = m.dreamStorageServiceClient.checkImage(
fileToBeStored,
contentType,
fileToBeStored!!,
contentType!!,
CheckImageRequest(false)
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,17 @@ package net.perfectdreams.galleryofdreams.backend.routes.api

import club.minnced.discord.webhook.send.AllowedMentions
import club.minnced.discord.webhook.send.WebhookMessageBuilder
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.server.application.*
import io.ktor.server.request.*
import io.ktor.server.util.*
import io.ktor.utils.io.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.io.readByteArray
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.json.Json
import net.perfectdreams.dreamstorageservice.data.api.CreateImageLinkRequest
Expand Down Expand Up @@ -41,18 +44,35 @@ class PostFanArtRoute(m: GalleryOfDreamsBackend) : RequiresAPIAuthenticationRout

// Receive the uploaded file
val multipart = call.receiveMultipart()
val parts = multipart.readAllParts()
val filePart = parts.first { it.name == "file" } as PartData.FileItem
val attributesPart = parts.first { it.name == "attributes" } as PartData.FormItem

val attributes = Json.decodeFromString<UploadFanArtRequest>(attributesPart.value)
var attributesString: String? = null
var contentType: ContentType? = null
var fileToBeStored: ByteArray? = null

val fileToBeStored = filePart.streamProvider.invoke().readAllBytes()
val contentType = filePart.contentType ?: error("Missing Content-Type!")
multipart.forEachPart { part ->
when (part) {
is PartData.FormItem -> {
if (part.name == "file")
attributesString = part.value
}

is PartData.FileItem -> {
if (part.name == "file") {
contentType = part.contentType
fileToBeStored = part.provider().readRemaining().readByteArray()
}
}

else -> {}
}
part.dispose()
}

val attributes = Json.decodeFromString<UploadFanArtRequest>(attributesString!!)

val uploadResult = m.dreamStorageServiceClient.uploadImage(
fileToBeStored,
contentType,
fileToBeStored ?: error("Missing fileToBeStored!"),
contentType ?: error("Missing Content-Type!"),
UploadImageRequest(false)
)

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package net.perfectdreams.sequins.ktor

import io.ktor.http.*
import io.ktor.server.application.*
import io.ktor.server.routing.*
import io.ktor.util.pipeline.*

/**
* A [BaseRoute] is used to register Ktor routes on the [routing] section, allowing you to split up routes in different classes.
*
* One of the advantages of using [BaseRoute] is that all routes are in different files, keeping the code base tidy and nice.
*
* Another advantage is that the HTTP Method is inferred from the class name, so, if the class is named `PostUserDataRoute`, the route will be
* registered as a POST instead of an GET.
*
* All HTTP Methods, except GET, needs to be explictly set in the class name.
*
* @param path the path's route
*/
abstract class BaseRoute(val path: String) {
abstract suspend fun onRequest(call: ApplicationCall)

fun register(routing: Routing) = registerWithPath(routing, path) { onRequest(call) }
fun registerWithPath(routing: Routing, path: String) = registerWithPath(routing, path) { onRequest(call) }

fun registerWithPath(routing: Routing, path: String, callback: RoutingHandler) {
val method = getMethod()
when (method) {
HttpMethod.Get -> routing.get(path, callback)
HttpMethod.Post -> routing.post(path, callback)
HttpMethod.Patch -> routing.patch(path, callback)
HttpMethod.Put -> routing.put(path, callback)
HttpMethod.Delete -> routing.delete(path, callback)
else -> routing.get(path, callback)
}
}

open fun getMethod(): HttpMethod {
val className = this::class.simpleName?.lowercase() ?: "Unknown"
return when {
className.startsWith("get") -> HttpMethod.Get
className.startsWith("post") -> HttpMethod.Post
className.startsWith("patch") -> HttpMethod.Patch
className.startsWith("put") -> HttpMethod.Put
className.startsWith("delete") -> HttpMethod.Delete
else -> HttpMethod.Get
}
}
}
2 changes: 1 addition & 1 deletion buildSrc/src/main/kotlin/Versions.kt
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ object Versions {
const val JIB = "3.2.1"
const val KOTLINX_SERIALIZATION = "1.6.0"
const val PROMETHEUS = "0.12.0"
const val KTOR = "2.3.3"
const val KTOR = "3.0.0"
const val I18N_HELPER = "0.0.5-SNAPSHOT"
}

0 comments on commit 6fd711d

Please sign in to comment.