From e068f588177036052c456767de3cdd3e11cc8136 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Mart=C3=ADnez?= Date: Sat, 28 Sep 2024 07:58:50 +0200 Subject: [PATCH] Add Kotlin Ktor Hello world example (#3621) Part of #3611 Working in the TodoMVC demo application. I'll raise a follow up PR for that. --- example/kotlinlib/web/1-hello-ktor/build.mill | 38 +++++++++++++++++++ .../1-hello-ktor/src/com/example/HelloKtor.kt | 20 ++++++++++ .../test/src/com/example/HelloKtor.kt | 22 +++++++++++ example/package.mill | 1 + 4 files changed, 81 insertions(+) create mode 100644 example/kotlinlib/web/1-hello-ktor/build.mill create mode 100644 example/kotlinlib/web/1-hello-ktor/src/com/example/HelloKtor.kt create mode 100644 example/kotlinlib/web/1-hello-ktor/test/src/com/example/HelloKtor.kt diff --git a/example/kotlinlib/web/1-hello-ktor/build.mill b/example/kotlinlib/web/1-hello-ktor/build.mill new file mode 100644 index 00000000000..53eb7c86ef8 --- /dev/null +++ b/example/kotlinlib/web/1-hello-ktor/build.mill @@ -0,0 +1,38 @@ +//// SNIPPET:BUILD +package build +import mill._, kotlinlib._ + +object `package` extends RootModule with KotlinModule { + + def kotlinVersion = "1.9.24" + + def mainClass = Some("com.example.HelloKtorKt") + + def ivyDeps = Agg( + ivy"io.ktor:ktor-server-core-jvm:2.3.12", + ivy"io.ktor:ktor-server-netty-jvm:2.3.12" + ) + + object test extends KotlinModuleTests with TestModule.Junit5 { + def ivyDeps = super.ivyDeps() ++ Agg( + ivy"io.kotest:kotest-runner-junit5-jvm:5.9.1", + ivy"io.ktor:ktor-server-test-host-jvm:2.3.12" + ) + } +} + +// This example demonstrates how to set up a simple webserver +// serving a single "

Hello, World!

" web page using Kotlin and Ktor + +/** Usage + +> mill test + +> mill runBackground + +> curl http://localhost:8080 +...

Hello, World!

... + +> mill clean runBackground + +*/ \ No newline at end of file diff --git a/example/kotlinlib/web/1-hello-ktor/src/com/example/HelloKtor.kt b/example/kotlinlib/web/1-hello-ktor/src/com/example/HelloKtor.kt new file mode 100644 index 00000000000..fb1fb9d3d7a --- /dev/null +++ b/example/kotlinlib/web/1-hello-ktor/src/com/example/HelloKtor.kt @@ -0,0 +1,20 @@ +package com.example + +import io.ktor.server.application.* +import io.ktor.server.engine.* +import io.ktor.server.netty.* +import io.ktor.server.response.* +import io.ktor.server.routing.* + +fun main() { + embeddedServer(Netty, port = 8080, host = "0.0.0.0", module = Application::module) + .start(wait = true) +} + +fun Application.module() { + routing { + get("/") { + call.respondText("

Hello, World!

") + } + } +} diff --git a/example/kotlinlib/web/1-hello-ktor/test/src/com/example/HelloKtor.kt b/example/kotlinlib/web/1-hello-ktor/test/src/com/example/HelloKtor.kt new file mode 100644 index 00000000000..828462004d6 --- /dev/null +++ b/example/kotlinlib/web/1-hello-ktor/test/src/com/example/HelloKtor.kt @@ -0,0 +1,22 @@ +package com.example + +import io.ktor.client.request.* +import io.ktor.client.statement.* +import io.ktor.http.* +import io.ktor.server.testing.* + +import io.kotest.core.spec.style.FunSpec +import io.kotest.matchers.shouldBe + +class HelloKtorTest: FunSpec({ + test("HelloKtorTest") { + testApplication { + application { + module() + } + val response = client.get("/") + response.status shouldBe HttpStatusCode.OK + response.bodyAsText() shouldBe "

Hello, World!

" + } + } +}) diff --git a/example/package.mill b/example/package.mill index 3ee18f56f75..9544d316c76 100644 --- a/example/package.mill +++ b/example/package.mill @@ -43,6 +43,7 @@ object `package` extends RootModule with Module { object module extends Cross[ExampleCrossModuleKotlin](build.listIn(millSourcePath / "module")) object publishing extends Cross[ExampleCrossModuleKotlin](build.listIn(millSourcePath / "publishing")) object testing extends Cross[ExampleCrossModuleKotlin](build.listIn(millSourcePath / "testing")) + object web extends Cross[ExampleCrossModuleKotlin](build.listIn(millSourcePath / "web")) } object scalalib extends Module { object basic extends Cross[ExampleCrossModule](build.listIn(millSourcePath / "basic"))