From 2b5380f8d66177ab30b10457ec28e296fc7c3fa8 Mon Sep 17 00:00:00 2001 From: InsanusMokrassar Date: Tue, 22 Nov 2022 13:38:36 +0600 Subject: [PATCH] add server part of uniUpload, fill changelog --- CHANGELOG.md | 8 ++++ .../inmo/micro_utils/ktor/client/UniUpload.kt | 2 +- .../ktor/client/ActualUniUpload.kt | 5 ++- .../ktor/client/ActualUniUpload.kt | 32 +++++++------ .../ktor/server/UniloadMultipart.kt | 45 +++++++++++++------ 5 files changed, 63 insertions(+), 29 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 5bbb54e0e7b..52c6f0333bc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,14 @@ ## 0.14.3 +* `Common`: + * New type `Progress` +* `Ktor`: + * `Client`: + * New universal `uniUpload` extension for `HttpClient` + * `Server`: + * New universal `handleUniUpload` extension for `ApplicationCall` + ## 0.14.2 * `Versions`: diff --git a/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/UniUpload.kt b/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/UniUpload.kt index 10a85ea73bf..6bef13f2f33 100644 --- a/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/UniUpload.kt +++ b/ktor/client/src/commonMain/kotlin/dev/inmo/micro_utils/ktor/client/UniUpload.kt @@ -21,7 +21,7 @@ data class UniUploadFileInfo( * [dev.inmo.micro_utils.common.MPPFile] (File from JS or JVM platform). Also you may pass [UniUploadFileInfo] as value * in case you wish to pass other source of multipart binary data than regular file */ -expect suspend fun HttpClient.uniupload( +expect suspend fun HttpClient.uniUpload( url: String, data: Map, resultDeserializer: DeserializationStrategy, diff --git a/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt b/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt index 6e6160449e1..4d2358dee02 100644 --- a/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt +++ b/ktor/client/src/jsMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt @@ -25,7 +25,7 @@ import org.w3c.xhr.XMLHttpRequestResponseType * [dev.inmo.micro_utils.common.MPPFile] (File from JS or JVM platform). Also you may pass [UniUploadFileInfo] as value * in case you wish to pass other source of multipart binary data than regular file */ -actual suspend fun HttpClient.uniupload( +actual suspend fun HttpClient.uniUpload( url: String, data: Map, resultDeserializer: DeserializationStrategy, @@ -55,6 +55,9 @@ actual suspend fun HttpClient.uniupload( } val request = XMLHttpRequest() + headers.forEach { s, strings -> + request.setRequestHeader(s, strings.joinToString()) + } request.responseType = XMLHttpRequestResponseType.TEXT request.upload.onprogress = { onUpload(it.loaded.toLong(), it.total.toLong()) diff --git a/ktor/client/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt b/ktor/client/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt index 98342c32854..27661c479f0 100644 --- a/ktor/client/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt +++ b/ktor/client/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/client/ActualUniUpload.kt @@ -2,11 +2,14 @@ package dev.inmo.micro_utils.ktor.client import dev.inmo.micro_utils.common.Progress import io.ktor.client.HttpClient +import io.ktor.client.engine.mergeHeaders import io.ktor.client.plugins.onUpload +import io.ktor.client.request.HttpRequestBuilder import io.ktor.client.request.forms.InputProvider import io.ktor.client.request.forms.formData import io.ktor.client.request.forms.submitForm import io.ktor.client.request.forms.submitFormWithBinaryData +import io.ktor.client.request.headers import io.ktor.client.statement.bodyAsText import io.ktor.http.Headers import io.ktor.http.HttpHeaders @@ -25,7 +28,7 @@ import java.io.File * [dev.inmo.micro_utils.common.MPPFile] (File from JS or JVM platform). Also you may pass [UniUploadFileInfo] as value * in case you wish to pass other source of multipart binary data than regular file */ -actual suspend fun HttpClient.uniupload( +actual suspend fun HttpClient.uniUpload( url: String, data: Map, resultDeserializer: DeserializationStrategy, @@ -62,15 +65,21 @@ actual suspend fun HttpClient.uniupload( } } + val requestBuilder: HttpRequestBuilder.() -> Unit = { + headers { + appendAll(headers) + } + onUpload { bytesSentTotal, contentLength -> + onUpload(bytesSentTotal, contentLength) + } + } + val response = if (withBinary) { submitFormWithBinaryData( url, - formData - ) { - onUpload { bytesSentTotal, contentLength -> - onUpload(bytesSentTotal, contentLength) - } - } + formData, + block = requestBuilder + ) } else { submitForm( url, @@ -79,12 +88,9 @@ actual suspend fun HttpClient.uniupload( val formItem = (it as PartData.FormItem) append(it.name!!, it.value) } - } - ) { - onUpload { bytesSentTotal, contentLength -> - onUpload(bytesSentTotal, contentLength) - } - } + }, + block = requestBuilder + ) } return if (response.status == HttpStatusCode.OK) { diff --git a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/UniloadMultipart.kt b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/UniloadMultipart.kt index 76a34745070..9dd60970509 100644 --- a/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/UniloadMultipart.kt +++ b/ktor/server/src/jvmMain/kotlin/dev/inmo/micro_utils/ktor/server/UniloadMultipart.kt @@ -7,29 +7,46 @@ import io.ktor.server.application.ApplicationCall import io.ktor.server.request.receiveMultipart import io.ktor.utils.io.core.* +/** + * Server-side part which receives [dev.inmo.micro_utils.ktor.client.uniUpload] request + */ +suspend fun ApplicationCall.handleUniUpload( + onFormItem: (PartData.FormItem) -> Unit = {}, + onFileItem: (PartData.FileItem) -> Unit = {}, + onBinaryChannelItem: (PartData.BinaryChannelItem) -> Unit = {}, + onBinaryContent: (PartData.BinaryItem) -> Unit = {} +) { + val multipartData = receiveMultipart() + + multipartData.forEachPart { + when (it) { + is PartData.FormItem -> onFormItem(it) + is PartData.FileItem -> onFileItem(it) + is PartData.BinaryItem -> onBinaryContent(it) + is PartData.BinaryChannelItem -> onBinaryChannelItem(it) + } + } +} + 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) - } + handleUniUpload( + onFormItem, + { + when (it.name) { + "bytes" -> resultInput = it.provider() + else -> onCustomFileItem(it) } - is PartData.BinaryItem -> onBinaryContent(it) - is PartData.BinaryChannelItem -> onBinaryChannelItem(it) - } - } + }, + onBinaryChannelItem, + onBinaryContent + ) resultInput ?: error("Bytes has not been received") }