Skip to content

Commit

Permalink
fixup! KTOR-5410 Fix server ContentConverter not triggered
Browse files Browse the repository at this point in the history
  • Loading branch information
e5l committed Jan 17, 2023
1 parent 8827dc5 commit b174455
Show file tree
Hide file tree
Showing 4 changed files with 186 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,15 @@ import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.testing.*
import io.ktor.server.testing.internal.*
import io.ktor.util.reflect.*
import io.ktor.utils.io.*
import io.ktor.utils.io.charsets.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.*
import java.io.*
import kotlin.test.*
import kotlin.text.toByteArray

class ContentNegotiationJvmTest {
private val alwaysFailingConverter = object : ContentConverter {
Expand Down Expand Up @@ -103,3 +107,48 @@ class ContentNegotiationJvmTest {
assertEquals("""{"x": 123}""", response)
}
}

@OptIn(DelicateCoroutinesApi::class)
internal fun buildMultipart(
boundary: String,
parts: List<PartData>
): ByteReadChannel = GlobalScope.writer(Dispatchers.IO) {
if (parts.isEmpty()) return@writer

try {
append("\r\n\r\n")
parts.forEach {
append("--$boundary\r\n")
for ((key, values) in it.headers.entries()) {
append("$key: ${values.joinToString(";")}\r\n")
}
append("\r\n")
append(
when (it) {
is PartData.FileItem -> {
channel.writeFully(it.provider().readBytes())
""
}
is PartData.BinaryItem -> {
channel.writeFully(it.provider().readBytes())
""
}
is PartData.FormItem -> it.value
is PartData.BinaryChannelItem -> {
it.provider().copyTo(channel)
""
}
}
)
append("\r\n")
}

append("--$boundary--\r\n")
} finally {
parts.forEach { it.dispose() }
}
}.channel

private suspend fun WriterScope.append(str: String, charset: Charset = Charsets.UTF_8) {
channel.writeFully(str.toByteArray(charset))
}
Original file line number Diff line number Diff line change
Expand Up @@ -138,11 +138,53 @@ public fun TestApplicationRequest.setBody(value: ByteReadPacket) {
bodyChannel = ByteReadChannel(value.readBytes())
}

/**
* Sets a multipart HTTP request body.
*/
public fun TestApplicationRequest.setBody(boundary: String, parts: List<PartData>) {
bodyChannel = writer(Dispatchers.IOBridge) {
if (parts.isEmpty()) return@writer

try {
append("\r\n\r\n")
parts.forEach {
append("--$boundary\r\n")
for ((key, values) in it.headers.entries()) {
append("$key: ${values.joinToString(";")}\r\n")
}
append("\r\n")
append(
when (it) {
is PartData.FileItem -> {
channel.writeFully(it.provider().readBytes())
""
}
is PartData.BinaryItem -> {
channel.writeFully(it.provider().readBytes())
""
}
is PartData.FormItem -> it.value
is PartData.BinaryChannelItem -> {
it.provider().copyTo(channel)
""
}
}
)
append("\r\n")
}

append("--$boundary--\r\n")
} finally {
parts.forEach { it.dispose() }
}
}.channel
}

/**
* Sets a multipart HTTP request body.
*/
@OptIn(DelicateCoroutinesApi::class)
public fun buildMultipart(
internal fun buildMultipart(
boundary: String,
parts: List<PartData>
): ByteReadChannel = GlobalScope.writer(Dispatchers.IOBridge) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,16 @@ import io.ktor.server.request.*
import io.ktor.server.response.*
import io.ktor.server.routing.*
import io.ktor.server.sessions.*
import io.ktor.utils.io.*
import io.ktor.utils.io.charsets.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.*
import java.lang.Runnable
import java.util.concurrent.atomic.*
import kotlin.coroutines.*
import kotlin.system.*
import kotlin.test.*
import kotlin.text.Charsets

@Suppress("DEPRECATION")
class TestApplicationEngineTest {
Expand Down Expand Up @@ -280,3 +283,48 @@ class TestApplicationEngineTest {
}
}
}

@OptIn(DelicateCoroutinesApi::class)
internal fun buildMultipart(
boundary: String,
parts: List<PartData>
): ByteReadChannel = GlobalScope.writer {
if (parts.isEmpty()) return@writer

try {
append("\r\n\r\n")
parts.forEach {
append("--$boundary\r\n")
for ((key, values) in it.headers.entries()) {
append("$key: ${values.joinToString(";")}\r\n")
}
append("\r\n")
append(
when (it) {
is PartData.FileItem -> {
channel.writeFully(it.provider().readBytes())
""
}
is PartData.BinaryItem -> {
channel.writeFully(it.provider().readBytes())
""
}
is PartData.FormItem -> it.value
is PartData.BinaryChannelItem -> {
it.provider().copyTo(channel)
""
}
}
)
append("\r\n")
}

append("--$boundary--\r\n")
} finally {
parts.forEach { it.dispose() }
}
}.channel

private suspend fun WriterScope.append(str: String, charset: Charset = Charsets.UTF_8) {
channel.writeFully(str.toByteArray(charset))
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import io.ktor.server.request.*
import io.ktor.server.testing.*
import io.ktor.util.*
import io.ktor.utils.io.*
import io.ktor.utils.io.charsets.*
import io.ktor.utils.io.core.*
import kotlinx.coroutines.*
import kotlin.test.*
Expand Down Expand Up @@ -162,3 +163,48 @@ class TestEngineMultipartTest {
)
}
}

@OptIn(DelicateCoroutinesApi::class)
internal fun buildMultipart(
boundary: String,
parts: List<PartData>
): ByteReadChannel = GlobalScope.writer {
if (parts.isEmpty()) return@writer

try {
append("\r\n\r\n")
parts.forEach {
append("--$boundary\r\n")
for ((key, values) in it.headers.entries()) {
append("$key: ${values.joinToString(";")}\r\n")
}
append("\r\n")
append(
when (it) {
is PartData.FileItem -> {
channel.writeFully(it.provider().readBytes())
""
}
is PartData.BinaryItem -> {
channel.writeFully(it.provider().readBytes())
""
}
is PartData.FormItem -> it.value
is PartData.BinaryChannelItem -> {
it.provider().copyTo(channel)
""
}
}
)
append("\r\n")
}

append("--$boundary--\r\n")
} finally {
parts.forEach { it.dispose() }
}
}.channel

private suspend fun WriterScope.append(str: String, charset: Charset = Charsets.UTF_8) {
channel.writeFully(str.toByteArray(charset))
}

0 comments on commit b174455

Please sign in to comment.