Skip to content

Commit

Permalink
improve http
Browse files Browse the repository at this point in the history
  • Loading branch information
osoykan committed Nov 28, 2024
1 parent 61505a0 commit 8315c4f
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
package com.trendyol.stove.testing.e2e.http

import arrow.core.*
import com.trendyol.stove.testing.e2e.serialization.*
import com.trendyol.stove.testing.e2e.serialization.StoveSerde
import com.trendyol.stove.testing.e2e.system.*
import com.trendyol.stove.testing.e2e.system.abstractions.*
import com.trendyol.stove.testing.e2e.system.annotations.StoveDsl
Expand All @@ -19,8 +19,11 @@ import io.ktor.http.*
import io.ktor.serialization.*
import io.ktor.serialization.jackson.*
import io.ktor.util.*
import io.ktor.util.reflect.*
import kotlinx.coroutines.flow.Flow
import org.slf4j.LoggerFactory
import java.net.http.HttpClient
import java.nio.charset.Charset
import kotlin.time.*
import kotlin.time.Duration.Companion.seconds

Expand Down Expand Up @@ -143,6 +146,21 @@ class HttpSystem(
expect(it.body())
}.let { this }

suspend inline fun <reified TExpected : Any> readJsonStream(
uri: String,
queryParams: Map<String, String> = mapOf(),
headers: Map<String, String> = mapOf(),
token: Option<String> = None,
expect: (Flow<TExpected>) -> Unit
): HttpSystem = ktorHttpClient.prepareGet(relative(uri)) {
headers.forEach { (key, value) -> header(key, value) }
header(HttpHeaders.Accept, "application/x-ndjson")
queryParams.forEach { (key, value) -> parameter(key, value) }
token.map { header(HeaderConstants.AUTHORIZATION, HeaderConstants.bearer(it)) }
}.readJsonContentStream {
options.contentConverter.deserialize(Charset.defaultCharset(), typeInfo<TExpected>(), it) as TExpected
}.also { expect(it) }.let { return this }

@HttpDsl
suspend fun postAndExpectBodilessResponse(
uri: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.trendyol.stove.testing.e2e.http

import com.trendyol.stove.testing.e2e.serialization.StoveSerde
import io.ktor.client.statement.*
import io.ktor.http.*
import io.ktor.util.*
Expand All @@ -8,13 +9,33 @@ import kotlinx.coroutines.flow.*

@OptIn(InternalAPI::class)
@Suppress("unused")
suspend fun <T> HttpStatement.readJsonStream(transform: (line: String) -> T): Flow<T> = flow {
fun <T> HttpStatement.readJsonTextStream(transform: suspend (line: String) -> T): Flow<T> = flow {
execute {
check(it.status.isSuccess()) { "Request failed with status: ${it.status}" }
while (!it.content.isClosedForRead) {
it.content.readUTF8Line()?.let { line ->
emit(transform(line))
}
val line = it.content.readUTF8Line() ?: break
if (line.isBlank()) continue
emit(transform(line))
}
}
}

@OptIn(InternalAPI::class)
@Suppress("unused")
fun <T> HttpStatement.readJsonContentStream(transform: suspend (line: ByteReadChannel) -> T): Flow<T> = flow {
execute {
check(it.status.isSuccess()) { "Request failed with status: ${it.status}" }
while (!it.content.isClosedForRead) {
val line = it.content.readUTF8Line() ?: break
if (line.isBlank()) continue
emit(transform(ByteReadChannel(line)))
}
}
}

/**
* Serializes the items to a stream of JSON strings.
*/
fun <T : Any> StoveSerde<T, ByteArray>.serializeToStreamJson(items: List<T>): ByteArray = items
.joinToString("\n") { String(serialize(it)) }
.toByteArray()
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import io.kotest.matchers.*
import io.kotest.matchers.string.shouldContain
import io.ktor.client.request.*
import io.ktor.http.*
import kotlinx.coroutines.flow.toList
import java.time.Instant
import java.util.*

Expand Down Expand Up @@ -393,6 +394,31 @@ class HttpSystemTests : FunSpec({
}
}
}

test("serialize to application/x-ndjson") {
val expectedGetDtoName = UUID.randomUUID().toString()
val items = (1..10).map { TestDto(expectedGetDtoName) }

TestSystem.validate {
wiremock {
mockGetConfigure("/get-ndjson") { builder, serde ->
builder.willReturn(
aResponse()
.withHeader("Content-Type", "application/x-ndjson")
.withBody(serde.serializeToStreamJson(items))
)
}
}

http {
readJsonStream<TestDto>("/get-ndjson") { actual ->
val collected = actual.toList()
collected.size shouldBe 10
collected.forEach { it.name shouldBe expectedGetDtoName }
}
}
}
}
})

class HttpConsoleTesting : ConsoleSpec({ capturedOutput ->
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ class MongodbSystem internal constructor(
suspend inline fun <reified T : Any> save(
instance: T,
objectId: String = ObjectId().toHexString(),
collection: String = context.options.databaseOptions.default.collection,
collection: String = context.options.databaseOptions.default.collection
): MongodbSystem = mongoClient
.getDatabase(context.options.databaseOptions.default.name)
.getCollection<Document>(collection)
Expand Down

0 comments on commit 8315c4f

Please sign in to comment.