Finchを試してみる

FinchはFinagle(twitter製のサーバライブラリ)をベースにした、簡単に信頼性の高いAPIが構築できる、軽量なHttpフレームワークである。そして、ほぼFinagleと変わらないパフォーマンスを目指しているという。

定番のHello World

scalaの開発では、sbtというビルドツールをよく使われる。

sbt初めての方、素晴らしい記事をどうぞ:
https://qiita.com/prokosna/items/0728b73561955e631937

まずsbt用プロジェクトのディレクトリを用意する:

tree -L 3
.
├── build.sbt
├── project
│   ├── build.properties
│   └── target
├── src
│   └── main
│       └── scala
└── target

./build.sbtはベース設定で、./project/build.propertiesの記述で個別の設定を上書きすることができる。

まず./build.sbtに下記のように設定を書く:

// ビルド情報
name := "hello-world"
version := "1.0"

// バージョンを定義
val circeVersion = "0.11.1"
val finchVersion = "0.29.0"

// 依存を追加
libraryDependencies ++= Seq(
  "com.github.finagle" %% "finchx-core"  % finchVersion,
  "com.github.finagle" %% "finchx-circe"  % finchVersion,

  // JSONライブラリ https://circe.github.io/circe/
  "io.circe" %% "circe-generic" % circeVersion,
)

そして、アプリのエントリーポイントのsrc/main/scala/main.scalaを作る:

import cats.effect.IO
import com.twitter.finagle.{Http, Service}
import com.twitter.finagle.http.{Request, Response}
import com.twitter.util.Await
import io.finch._
import io.finch.catsEffect._
import io.finch.circe._
import io.circe.generic.auto._

// scalaではextends Appすることで、アプリケーションを作成する
// objectはscalaでのsingleton, 他の言語でのstaticだと思えば
object Main extends App {
  // クラス
  case class Message(hello: String)

  // デフォルトエンドポイント
  def healthcheck: Endpoint[IO, String] = get(pathEmpty) {
    Ok("OK")
  }

  // /helloエンドポイント
  def helloWorld: Endpoint[IO, Message] = get("hello") {
    Ok(Message("World"))
  }

  // /hello/{s} エンドポイント {s}はs:Stringに渡される
  def hello: Endpoint[IO, Message] = get("hello" :: path[String]) { s: String =>
    Ok(Message(s))
  }

  // サーバーを初期化
  // エンドポイントの登録など
  def service: Service[Request, Response] = Bootstrap
    .serve[Text.Plain](healthcheck)
    .serve[Application.Json](helloWorld :+: hello)
    .toService

  // listen
  Await.ready(Http.server.serve(":8081", service))
}

最後に

sbt run

でコンパイル+実行。

サーバー無事にupになったら、下記のエンドポイントをアクセスしてみると、下記のリスポンスパターンが確認することができる。

curl http://localhost:8081
OK
curl http://localhost:8081/hello
{"hello":"World"}
curl http://localhost:8081/hello/my-finch
{"hello":"my-finch"}
curl http://localhost:8081/hello/my-finch/and-world
表示なし(HTTP ERROR 404)

最後に

単純なAPIを作るなら意外と簡単だが、他のサービス(DB、キャッシュ)など絡んで作る場合はどうなるんだろうと思いつづも、scalaのエレガントさに魅力を感じた。まだ中身しっかり理解してないが、次回はすこし中身を少し解読して共有しようと思う。