Skip to content

Commit 8c7d26a

Browse files
authored
Replace Java HttpClient with Ktor Http Client and add support for multi-part form data post (#404)
1 parent 48af208 commit 8c7d26a

File tree

10 files changed

+959
-159
lines changed

10 files changed

+959
-159
lines changed

detekt.yml

Lines changed: 672 additions & 0 deletions
Large diffs are not rendered by default.

examples/spring-example/src/main/kotlin/stove/spring/example/infrastructure/api/ProductController.kt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,14 @@
11
package stove.spring.example.infrastructure.api
22

3+
import kotlinx.coroutines.reactive.*
4+
import kotlinx.coroutines.reactor.mono
5+
import org.springframework.http.codec.multipart.FilePart
36
import org.springframework.web.bind.annotation.GetMapping
47
import org.springframework.web.bind.annotation.PostMapping
58
import org.springframework.web.bind.annotation.RequestBody
69
import org.springframework.web.bind.annotation.RequestMapping
710
import org.springframework.web.bind.annotation.RequestParam
11+
import org.springframework.web.bind.annotation.RequestPart
812
import org.springframework.web.bind.annotation.RestController
913
import stove.spring.example.application.handlers.ProductCreateRequest
1014
import stove.spring.example.application.handlers.ProductCreator
@@ -25,4 +29,16 @@ class ProductController(private val productCreator: ProductCreator) {
2529
): String {
2630
return productCreator.create(productCreateRequest)
2731
}
32+
33+
@PostMapping("/product/import")
34+
suspend fun importFile(
35+
@RequestPart(name = "name") name: String,
36+
@RequestPart(name = "file") file: FilePart
37+
): String {
38+
val content = file.content()
39+
.flatMap { mono { it.asInputStream().readAllBytes() } }
40+
.awaitSingle()
41+
.let { String(it) }
42+
return "File ${file.filename()} is imported with $name and content: $content"
43+
}
2844
}

examples/spring-example/src/test/kotlin/com/stove/spring/example/e2e/ExampleTest.kt

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,15 @@ package com.stove.spring.example.e2e
22

33
import arrow.core.some
44
import com.trendyol.stove.testing.e2e.couchbase.couchbase
5-
import com.trendyol.stove.testing.e2e.http.http
5+
import com.trendyol.stove.testing.e2e.http.*
66
import com.trendyol.stove.testing.e2e.kafka.kafka
77
import com.trendyol.stove.testing.e2e.system.TestSystem
88
import com.trendyol.stove.testing.e2e.using
99
import com.trendyol.stove.testing.e2e.wiremock.wiremock
1010
import io.kotest.core.spec.style.FunSpec
1111
import io.kotest.matchers.shouldBe
1212
import io.kotest.matchers.string.shouldContain
13+
import org.springframework.http.MediaType
1314
import stove.spring.example.application.handlers.*
1415
import stove.spring.example.application.services.SupplierPermission
1516
import stove.spring.example.infrastructure.couchbase.CouchbaseProperties
@@ -165,4 +166,25 @@ class ExampleTest : FunSpec({
165166
}
166167
}
167168
}
169+
170+
test("file import should work") {
171+
TestSystem.validate {
172+
http {
173+
postMultipartAndExpectResponse<String>(
174+
"/api/product/import",
175+
body = listOf(
176+
StoveMultiPartContent.Text("name", "product name"),
177+
StoveMultiPartContent.File(
178+
"file",
179+
"file.txt",
180+
"file".toByteArray(),
181+
contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE
182+
)
183+
)
184+
) { actual ->
185+
actual.body() shouldBe "File file.txt is imported with product name and content: file"
186+
}
187+
}
188+
}
189+
}
168190
})

gradle/libs.versions.toml

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ r2dbc-spi = "1.0.0.RELEASE"
2727
r2dbc-postgresql = "0.8.13.RELEASE"
2828
elastic = "8.13.2"
2929
mongodb = "5.0.1"
30-
wiremock = "3.5.3"
30+
wiremock = "3.5.2"
3131
testcontainers = "1.19.7"
3232
r2dbc-mssql = "1.0.2.RELEASE"
3333
spotless = "6.25.0"
@@ -59,14 +59,20 @@ ktor-server = { module = "io.ktor:ktor-server", version.ref = "ktor" }
5959
ktor-server-call-logging = { module = "io.ktor:ktor-server-call-logging", version.ref = "ktor" }
6060
ktor-server-netty = { module = "io.ktor:ktor-server-netty", version.ref = "ktor" }
6161
ktor-serialization-kotlinx-json = { module = "io.ktor:ktor-serialization-kotlinx-json", version.ref = "ktor" }
62+
ktor-client-core = { module = "io.ktor:ktor-client-core", version.ref = "ktor" }
63+
ktor-client-cio = { module = "io.ktor:ktor-client-cio", version.ref = "ktor" }
64+
ktor-client-okhttp = { module = "io.ktor:ktor-client-okhttp", version.ref = "ktor" }
65+
ktor-client-plugins-logging = { module = "io.ktor:ktor-client-logging", version.ref = "ktor" }
66+
ktor-client-content-negotiation = { module = "io.ktor:ktor-client-content-negotiation", version.ref = "ktor" }
67+
ktor-serialization-jackson-json = { module = "io.ktor:ktor-serialization-jackson", version.ref = "ktor" }
6268
koin-ktor = { module = "io.insert-koin:koin-ktor", version.ref = "koin" }
6369
koin-logger-slf4j = { module = "io.insert-koin:koin-logger-slf4j", version.ref = "koin" }
6470
r2dbc-spi = { module = "io.r2dbc:r2dbc-spi", version.ref = "r2dbc-spi" }
6571
r2dbc-postgresql = { module = "io.r2dbc:r2dbc-postgresql", version.ref = "r2dbc-postgresql" }
6672
elastic = { module = "co.elastic.clients:elasticsearch-java", version.ref = "elastic" }
6773
mongodb-reactivestreams = { module = "org.mongodb:mongodb-driver-reactivestreams", version.ref = "mongodb" }
6874

69-
wiremock = { module = "org.wiremock:wiremock-standalone", version.ref = "wiremock" }
75+
wiremock-standalone = { module = "org.wiremock:wiremock-standalone", version.ref = "wiremock" }
7076
testcontainers = { module = "org.testcontainers:testcontainers", version.ref = "testcontainers" }
7177
testcontainers-jdbc = { module = "org.testcontainers:jdbc", version.ref = "testcontainers" }
7278
testcontainers-kafka = { module = "org.testcontainers:kafka", version.ref = "testcontainers" }
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
dependencies {
22
api(projects.lib.stoveTestingE2e)
3+
api(libs.ktor.client.core)
4+
api(libs.ktor.client.okhttp)
35
implementation(libs.kotlinx.core)
46
implementation(libs.kotlinx.io.reactor)
57
implementation(libs.kotlinx.reactive)
68
implementation(libs.kotlinx.jdk8)
9+
implementation(libs.ktor.client.plugins.logging)
10+
implementation(libs.ktor.client.content.negotiation)
11+
implementation(libs.ktor.serialization.jackson.json)
712
testImplementation(projects.lib.stoveTestingE2eWiremock)
813
}

0 commit comments

Comments
 (0)