Skip to content

Commit 1d3346e

Browse files
Add an implementation of the example using Ktor (#6)
1 parent 2e36501 commit 1d3346e

File tree

3 files changed

+108
-0
lines changed

3 files changed

+108
-0
lines changed

examples/README.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,11 @@ This example uses the plain Java `HttpServer` to serve the front end. ([code](ja
2929
```shell
3030
cd ./java-httpserver ; jbang server.kt ; cd ..
3131
```
32+
33+
### Ktor
34+
35+
This example uses the `Ktor` to serve the front end. ([code](ktor/server.kt))
36+
37+
```shell
38+
cd ./ktor ; jbang server.kt ; cd ..
39+
```

examples/java-httpserver/server.kt

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ fun server(
4848
this@sseContext.patchElements(
4949
"""<span id="counter">${event}</span>"""
5050
)
51+
if (event == 3) {
52+
this@sseContext.executeScript("""alert('Thanks for trying Datastar!')""")
53+
}
5154
}
5255
}
5356
}

examples/ktor/server.kt

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
import dev.datastar.kotlin.sdk.Response
2+
import dev.datastar.kotlin.sdk.ServerSentEventGenerator
3+
import io.ktor.http.ContentType
4+
import io.ktor.http.HttpStatusCode.Companion.NoContent
5+
import io.ktor.http.HttpStatusCode.Companion.OK
6+
import io.ktor.server.engine.embeddedServer
7+
import io.ktor.server.netty.Netty
8+
import io.ktor.server.response.respondBytes
9+
import io.ktor.server.response.respondTextWriter
10+
import io.ktor.server.routing.get
11+
import io.ktor.server.routing.post
12+
import io.ktor.server.routing.routing
13+
import kotlinx.coroutines.flow.MutableStateFlow
14+
import java.io.File
15+
import java.io.Writer
16+
17+
///usr/bin/env jbang "$0" "$@" ; exit $?
18+
//JAVA 21
19+
//KOTLIN 2.2.0
20+
//DEPS dev.cloudgt.datastar:kotlin-sdk:0.1.0
21+
//DEPS io.ktor:ktor-server-core-jvm:3.2.3
22+
//DEPS io.ktor:ktor-server-netty-jvm:3.2.3
23+
24+
25+
fun main() {
26+
server().run {
27+
println("Let's go counting star... http://localhost:8080")
28+
start(wait = true)
29+
}
30+
}
31+
32+
fun server(
33+
counter: MutableStateFlow<Int> = MutableStateFlow(0),
34+
) = embeddedServer(Netty, port = 8080) {
35+
36+
val counterPage = File(
37+
"../front/counter.html"
38+
).readBytes()
39+
40+
routing {
41+
42+
get("/") {
43+
call.response.headers.append("Content-Type", "text/html")
44+
call.response.status(OK)
45+
call.respondBytes(counterPage)
46+
}
47+
48+
get("/counter") {
49+
call.respondTextWriter(
50+
status = OK,
51+
contentType = ContentType.Text.EventStream,
52+
) {
53+
54+
val response = adaptResponse(this)
55+
val generator = ServerSentEventGenerator(response)
56+
57+
counter.collect { event ->
58+
generator.patchElements("""<span id="counter">${event}</span>""")
59+
60+
if (event == 3) {
61+
generator.executeScript("""alert('Thanks for trying Datastar!')""")
62+
}
63+
}
64+
65+
}
66+
}
67+
68+
post("/increment") {
69+
counter.value++
70+
call.response.status(NoContent)
71+
}
72+
73+
post("/decrement") {
74+
counter.value--
75+
call.response.status(NoContent)
76+
}
77+
78+
}
79+
}
80+
81+
private fun adaptResponse(writer: Writer): Response =
82+
object : Response {
83+
override fun sendConnectionHeaders(
84+
status: Int,
85+
headers: Map<String, List<String>>,
86+
) {
87+
// connection is already set up when used
88+
}
89+
90+
override fun write(text: String) {
91+
writer.write(text)
92+
}
93+
94+
override fun flush() {
95+
writer.flush()
96+
}
97+
}

0 commit comments

Comments
 (0)