|
1 | 1 | package com.coditory.ktserver.nio |
2 | 2 |
|
| 3 | +import com.coditory.ktserver.HttpExchange |
| 4 | +import com.coditory.ktserver.HttpSerDeserializer |
3 | 5 | import com.coditory.ktserver.HttpServer |
| 6 | +import com.coditory.ktserver.http.HttpParams |
| 7 | +import com.coditory.ktserver.http.HttpRequest |
| 8 | +import com.coditory.ktserver.http.HttpRequestMethod |
| 9 | +import com.coditory.ktserver.serialization.ScoredHttpSerDeserializer |
4 | 10 | import com.coditory.quark.uri.Ports |
5 | 11 | import kotlinx.coroutines.CoroutineScope |
6 | 12 | import kotlinx.coroutines.Dispatchers |
7 | 13 | import kotlinx.coroutines.launch |
8 | | -import kotlinx.coroutines.runBlocking |
9 | | -import kotlinx.coroutines.suspendCancellableCoroutine |
10 | | -import kotlinx.io.Buffer |
11 | 14 | import kotlinx.io.asSource |
12 | 15 | import kotlinx.io.buffered |
13 | | -import kotlinx.io.readString |
14 | 16 | import java.net.InetSocketAddress |
15 | | -import java.nio.channels.AsynchronousServerSocketChannel |
16 | | -import java.nio.channels.AsynchronousSocketChannel |
17 | | -import kotlin.coroutines.resume |
18 | | -import kotlin.coroutines.resumeWithException |
| 17 | +import com.sun.net.httpserver.HttpExchange as JdkHttpExchange |
19 | 18 | import com.sun.net.httpserver.HttpServer as JdkHttpServer |
20 | 19 |
|
21 | 20 | class KtJdkServer( |
22 | 21 | val port: Int = Ports.getNextAvailable(), |
23 | 22 | val backlog: Int = 0, |
24 | 23 | val requestScope: CoroutineScope = CoroutineScope(Dispatchers.IO), |
| 24 | + val serde: HttpSerDeserializer = ScoredHttpSerDeserializer.default(), |
25 | 25 | ) : HttpServer { |
26 | | - private val server = JdkHttpServer.create(InetSocketAddress(port), 0).apply { |
27 | | - executor = null // creates a default executor |
| 26 | + private val server = JdkHttpServer.create(InetSocketAddress(port), backlog).apply { |
| 27 | + executor = null // creates a default executor that runs on callers thread |
28 | 28 | createContext("/") { exchange -> |
29 | 29 | requestScope.launch { |
30 | | - val src = exchange.requestBody.asSource().buffered() |
31 | | - src.readString() |
32 | 30 | handleRequest(exchange) |
33 | 31 | } |
34 | 32 | } |
35 | 33 | } |
36 | 34 |
|
37 | | - override fun start() { |
38 | | - val server = AsynchronousServerSocketChannel.open().bind(InetSocketAddress(port), backlog) |
39 | | - runBlocking { |
40 | | - val channel = accept(server) |
41 | | - val asyncChannel = HttpAsyncSocketChannel(channel) |
42 | | - Buffer |
43 | | - } |
44 | | - } |
45 | | - |
46 | | - suspend fun accept(server: AsynchronousServerSocketChannel): AsynchronousSocketChannel { |
47 | | - suspendCancellableCoroutine { cont -> |
48 | | - server.accept( |
49 | | - null, |
50 | | - object : java.nio.channels.CompletionHandler<AsynchronousSocketChannel, Void?> { |
51 | | - override fun completed(result: AsynchronousSocketChannel, attachment: Void?) { |
52 | | - cont.resume(result) |
53 | | - } |
54 | | - |
55 | | - override fun failed(exc: Throwable, attachment: Void?) { |
56 | | - cont.resumeWithException(exc) |
57 | | - } |
58 | | - }, |
59 | | - ) |
60 | | - } |
| 35 | + private suspend fun handleRequest(srcExchange: JdkHttpExchange) { |
| 36 | + val request = HttpRequest( |
| 37 | + method = HttpRequestMethod.valueOf(srcExchange.requestMethod), |
| 38 | + uri = srcExchange.requestURI, |
| 39 | + headers = HttpParams.fromMultiMap(srcExchange.requestHeaders.toMap()), |
| 40 | + deserializer = serde, |
| 41 | + source = srcExchange.requestBody.asSource().buffered(), |
| 42 | + ) |
| 43 | + val exchange = HttpExchange(request = request) |
61 | 44 | } |
62 | 45 |
|
63 | | - private suspend fun handleRequest(channel: HttpAsyncSocketChannel) { |
64 | | - try { |
65 | | - // Read the request from the client |
66 | | - val requestLine = source.readUtf8Line() |
67 | | - println("Received request: $requestLine") |
68 | | - |
69 | | - // Prepare an HTTP-like response |
70 | | - val body = "Hello from non-blocking Okio!" |
71 | | - val response = """ |
72 | | - HTTP/1.1 200 OK |
73 | | - Content-Type: text/plain |
74 | | - Content-Length: ${body.length} |
75 | | -
|
76 | | - $body |
77 | | - """.trimIndent() |
78 | | - |
79 | | - // Write the response to the client |
80 | | - sink.writeUtf8(response) |
81 | | - sink.flush() |
82 | | - } catch (e: Exception) { |
83 | | - println("Error while handling client: ${e.message}") |
84 | | - } finally { |
85 | | - channel.close() |
86 | | - } |
| 46 | + override fun start() { |
87 | 47 | } |
88 | 48 |
|
89 | 49 | override fun stop() { |
|
0 commit comments