この記事はkdnaktの1人 Advent Calendar 2020の20日目の記事です(1日遅れ)。
2020年は会社でKotlin dojoを主催して週1回30分Kotlinと戯れていました。12月はその集大成ということで、Kotlin/NativeでHTTPサーバーを作ってみたいと思います。どこまでできるか、お楽しみ……。
[kotlinx-cli]
19日目はPOSTメソッドへ対応するために、リクエストヘッダーをKotlinオブジェクトにパースする実装を行いました。引き続きPOSTメソッドの実装を進めたいところですが、GETメソッドと処理を分岐させる部分が出てくるため、既存のmain()
関数内の処理がデグレードを起こさないか心配です。
そこで、main()
関数内の処理を外部からテストするために、テスト用のポートでHTTPサーバーを起動できるようにします。
HTTPサーバーの起動時に、kttpd.kexe -p 3000
のように引数を渡してポート番号を変更するために、kotlinx-cli
を利用できるようにします。
README.mdに記載のとおり、build.gradle.kts
に1行追加します。
kotlin { macosX64("native") { + // For kotlinx-cli + compilations["main"].enableEndorsedLibs = true binaries { executable { entryPoint = "com.kdnakt.kttpd.main" } } } }
引き続き、README.mdの記載を参考にArgParserクラスを利用する処理を追加します*1。
[ポート番号を引数で受け取る]
ソケットのポート番号を指定する部分のコードは以下のようになっています。
with(serverAddr) { memset(this.ptr, 0, sizeOf<sockaddr_in>().convert()) sin_family = AF_INET.convert() sin_addr.s_addr = posix_htons(0).convert() sin_port = posix_htons(port).convert() }
ここで利用されているposix_htons
関数はShort
型の引数をとります。
しかし、kotlinx-cli
では、以下の型の引数しかデフォルトでは用意されていません。
- ArgType.Boolean
- ArgType.Int
- ArgType.String
- ArgType.Double
- ArgType.Choice
独自のArgTypeを定義することもできるようですが、Int型のArgTypeを利用して進めます。
ArgParserの第一引数はval programName: String
なので任意の文字列を入れることができます。
kotlinx-cli/ArgParser.kt at master · Kotlin/kotlinx-cli · GitHub
あとは、移譲(Delegation)を利用して起動時引数を定義してArgParser.parse()
を呼び出し、定義した引数を利用します。
fun main(args: Array) { val argsParser = ArgParser("kttpd") val port by argsParser.option(ArgType.Int, shortName="p").default(8080) argsParser.parse(args) // 省略 with(serverAddr) { memset(this.ptr, 0, sizeOf<sockaddr_in>().convert()) sin_family = AF_INET.convert() sin_addr.s_addr = posix_htons(0).convert() sin_port = posix_htons(port.toShort()).convert() } }
これで、起動時引数を利用することができるようになりました。
まずはヘルプを確認してみます。
$ ./build/bin/native/releaseExecutable/kttpd.kexe -h Usage: kttpd options_list Options: --port, -p [8080] { Int } --help, -h -> Usage info
雑ですが、kotlinx-cli
がデフォルトで提供している形でヘルプが表示されました。定義した変数名がそのまま起動時引数の正式名称として利用できるようです。
次に、ポート指定でのHTTPサーバーの起動を試します。
$ ./build/bin/native/releaseExecutable/kttpd.kexe --port 1234 kttpd start!
ブラウザでhttp://localhost:1234/index.html
にアクセスすると、無事index.htmlの内容が表示されました。
[まとめ]
- Kotlin/Nativeの場合、kotlinx-cliを利用するための設定変更は1行で済む
- kotlinx-cliを利用してヘルプを表示した
- kotlinx-cliを利用して、HTTPサーバーのポートを起動時に指定可能とした
- 実装中のコードは以下のリポジトリにまとめてある