MicroUtils/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/ServerRoutingShortcuts.kt

112 lines
3.8 KiB
Kotlin

package dev.inmo.micro_utils.ktor.server
import dev.inmo.micro_utils.common.*
import dev.inmo.micro_utils.coroutines.safely
import dev.inmo.micro_utils.ktor.common.*
import io.ktor.http.*
import io.ktor.http.content.*
import io.ktor.server.application.ApplicationCall
import io.ktor.server.application.call
import io.ktor.server.request.receive
import io.ktor.server.request.receiveMultipart
import io.ktor.server.response.respond
import io.ktor.server.response.respondBytes
import io.ktor.server.routing.Route
import io.ktor.server.websocket.WebSocketServerSession
import io.ktor.util.pipeline.PipelineContext
import io.ktor.utils.io.core.*
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.DeserializationStrategy
import kotlinx.serialization.SerializationStrategy
suspend fun ApplicationCall.uniloadMultipart(
onFormItem: (PartData.FormItem) -> Unit = {},
onCustomFileItem: (PartData.FileItem) -> Unit = {},
onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
onBinaryContent: (PartData.BinaryItem) -> Unit = {}
) = safely {
val multipartData = receiveMultipart()
var resultInput: Input? = null
multipartData.forEachPart {
when (it) {
is PartData.FormItem -> onFormItem(it)
is PartData.FileItem -> {
when (it.name) {
"bytes" -> resultInput = it.provider()
else -> onCustomFileItem(it)
}
}
is PartData.BinaryItem -> onBinaryContent(it)
is PartData.BinaryChannelItem -> onBinaryChannelItem(it)
}
}
resultInput ?: error("Bytes has not been received")
}
suspend fun ApplicationCall.uniloadMultipartFile(
onFormItem: (PartData.FormItem) -> Unit = {},
onCustomFileItem: (PartData.FileItem) -> Unit = {},
onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {},
onBinaryContent: (PartData.BinaryItem) -> Unit = {},
) = safely {
val multipartData = receiveMultipart()
var resultInput: MPPFile? = null
multipartData.forEachPart {
when (it) {
is PartData.FormItem -> onFormItem(it)
is PartData.FileItem -> {
if (it.name == "bytes") {
val name = FileName(it.originalFileName ?: error("File name is unknown for default part"))
resultInput = MPPFile.createTempFile(
name.nameWithoutExtension.let {
var resultName = it
while (resultName.length < 3) {
resultName += "_"
}
resultName
},
".${name.extension}"
).apply {
outputStream().use { fileStream ->
it.streamProvider().use {
it.copyTo(fileStream)
}
}
}
} else {
onCustomFileItem(it)
}
}
is PartData.BinaryItem -> onBinaryContent(it)
is PartData.BinaryChannelItem -> onBinaryChannelItem(it)
}
}
resultInput ?: error("Bytes has not been received")
}
suspend fun ApplicationCall.getParameterOrSendError(
field: String
) = parameters[field].also {
if (it == null) {
respond(HttpStatusCode.BadRequest, "Request must contains $field")
}
}
fun ApplicationCall.getQueryParameter(
field: String
) = request.queryParameters[field]
suspend fun ApplicationCall.getQueryParameterOrSendError(
field: String
) = getQueryParameter(field).also {
if (it == null) {
respond(HttpStatusCode.BadRequest, "Request query parameters must contains $field")
}
}