Andreas Scheja
10/30/2021, 3:02 PMMockEngine
? I want to test my client which is building a MultiPartFormDataContent
using the formData
builder (which by the way seems to lack support for appending files?).
Now my problem is that the request body in the MockEngine
is just a MultiPartFormDataContent
only exposing properties of OutgoingContent.WriteChannelContent
, which means I can only
get the full body with all boundary strings and headers written in it. My current
workaround is to more or less split the full body into somehow manageable parts, sadly
all methods I could find for parsing multipart/form-data
in ktor are either internal
already or marked as deprecated as they will become internal
in the future.
Am I overlooking something or is ktor's api just lacking in this area as of now?Aleksei Tirman [JB]
11/01/2021, 9:03 AM@OptIn(InternalAPI::class)
annotation to get rid of the internal API warning. Here is a complete example of the test:
import io.ktor.client.*
import io.ktor.client.engine.mock.*
import io.ktor.client.request.forms.*
import io.ktor.http.*
import io.ktor.http.cio.*
import io.ktor.http.content.*
import io.ktor.util.*
import io.ktor.utils.io.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.runBlocking
import org.junit.Test
import java.io.File
import kotlin.test.assertEquals
class SomeTest {
@OptIn(InternalAPI::class)
@Test
fun test(): Unit = runBlocking {
val client = HttpClient(MockEngine) {
engine {
addHandler { request ->
val body = request.body as OutgoingContent.WriteChannelContent
val channel = GlobalScope.writer(<http://Dispatchers.IO|Dispatchers.IO>) { body.writeTo(channel) }.channel
val result = CIOMultipartDataBase(Dispatchers.Unconfined, channel, body.contentType.toString(), body.contentLength)
val parts = result.readAllParts()
val description = parts[0] as PartData.FormItem
assertEquals("description", description.name)
assertEquals("Ktor logo", description.value)
val file = parts[1] as PartData.FileItem
assertEquals("image", file.name)
assertEquals("wiki.txt", file.originalFileName)
assertEquals("", file.provider().readText())
respond("")
}
}
}
client.submitFormWithBinaryData<String>(
url = "<http://localhost:8080/upload>",
formData = formData {
append("description", "Ktor logo")
append("image", File("files/wiki.txt").readBytes(), Headers.build {
append(HttpHeaders.ContentType, "plain/text")
append(HttpHeaders.ContentDisposition, "filename=wiki.txt")
})
}
)
}
}
Andreas Scheja
11/01/2021, 11:45 AM