この記事は リクルートライフスタイル Advent Calendar 2018 の9日目の記事です。
本日は、ホットペッパービューティーのAndroidアプリ開発を担当している @oxsoft が、KtorをAndroidで使ってみた話を書いてみたいと思います。
Ktorとは?
Kotlin製のWebフレームワークで、DSL形式で簡単に書くことができます。先日Ktor 1.0がリリースされました!
https://ktor.io/
Welcome Ktor 1.0, a connected applications framework built by the Kotlin team! Create asynchronous, high-performing, and lightweight web servers and build non-blocking multiplatform web clients, all in one language with idiomatic APIs.
— Kotlin (@kotlin) 2018年11月19日
https://t.co/tb1G6zefYI pic.twitter.com/bxzqXsNopG
公式のFAQにも書かれていますが、KtorはKotlinで書かれているので、Androidでも動きます。(ただし、API24以降)
https://ktor.io/quickstart/faq.html#android-support
今回作るもの
今回はKtorをAndroid上で動かして、簡単なモックサーバアプリを作ってみたいと思います。通常の開発用サーバに接続する場合と比較して、モックサーバアプリを作る利点としては以下のようなことが挙げられます。
- 特殊なレスポンスも簡単にモックできる
- エンジニア以外もGUIで簡単にレスポンスを変更できる
- 端末単位で環境を用意することができる
もちろんKtorを使わなくてもAndroid上にHTTPサーバを立てる方法はいくつかありますが、今回はKtorをAndroidで使ってみたいという気持ちがあるのでKtorを使います
環境構築
先述した通り、KtorはAPI24以降でしか動作しないので、まずはminSdkVersionを24以上にします
android {
defaultConfig {
minSdkVersion 24
}
}
そして、以下の依存関係を追加します。
dependencies {
implementation 'io.ktor:ktor-server-netty:1.0.0'
implementation 'org.slf4j:slf4j-android:1.7.25' // ログ出力用
}
また、重複ファイルのエラーが出るので、以下のファイルを除外します。
android {
packagingOptions {
exclude 'META-INF/io.netty.versions.properties'
exclude 'META-INF/INDEX.LIST'
}
}
当然、インターネットアクセスが必要となるため、以下のパーミッションも追加します。
<manifest>
<uses-permission android:name="android.permission.INTERNET" />
</manifest>
サーバーの起動
以下のコードをバックグラウンドスレッドから呼び出すことで、8080ポートにHTTPサーバを起動することができます。
embeddedServer(Netty, 8080) {
routing {
get("/") {
call.respondText("<h1>Hello world!</h1>", ContentType.Text.Html)
}
}
}.start(wait = true)
Chromeを開いてhttp://localhost:8080/
にアクセスすると、無事にHello world!
を表示する事ができました
また、CallLogging
を設定することにより、アクセスログを出力することができます。
embeddedServer(...) {
install(CallLogging) {
level = Level.INFO
}
...
}
I/ktor.application: 200 OK: GET - /
I/ktor.application: Unhandled: GET - /favicon.ico
リクエストの受付
今回はassets/response/
以下に用意したファイルを返却するようにします。URLのパスとassetsフォルダを対応させたいので、URLのパスをハンドリングします。パスのハンドリングは以下のように書くことで簡単に行うことができます。
get("/{path...}") {
val path = call.request.path()
}
ルーティングのパラメータ名をpath...
としていますが、今回は使っていないので実際には何でも大丈夫です。
もちろん、パラメータとしても受け取っているので、以下のようにしてもパスを取得することができます。(※スラッシュの有無などが、上記のパターンと異なります)
get("/{path...}") {
val path = call.parameters.getAll("path").orEmpty().joinToString("/")
}
ルーティングの詳しい文法は、以下のドキュメントに書いてあります。
https://ktor.io/servers/features/routing.html
レスポンスの返却
あとは、このパスに応じてassetsファイルを返却するだけです。
以下のような関数を用意しておいて、
fun readAsset(path: String) = BufferedReader(InputStreamReader(assets.open(path))).use { reader ->
reader.readLines().joinToString("\n")
}
レスポンス時に呼び出します。
call.respondText(readAsset("response$path"), ContentType.Application.Json)
これでモックサーバアプリは完成しました
ホットペッパービューティーのデバッグ版アプリでは、OkHttp3のInterceptorによってドメインを任意のものに差し替えるデバッグ機能があるので、それをlocalhost:8080
に指定することで接続できました
実際のモックサーバアプリでは、以下のような感じでAPIごとにモックするレスポンスを変更することができるようにしましたが、特に記事にするほどのことをしていないので、今回は割愛します。
まとめ
ほとんどつまづくことなく、簡単にHTTPサーバを立てることができました
今年も残りわずかとなりましたが、来年もまたAndroid/Kotlin界隈がより一層盛り上がっていくのが楽しみですね!それではみなさん良いお年を