4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

finchを試してみた

Last updated at Posted at 2018-03-14

軽量finchを試してみました。2018年2月リリースのfinchを落としてきて、参考リンクのコーディングを基に動かそうとしたが、コンパイルが通らなかったので手を加えてみました。

build.sbt

libraryDependencies ++= Seq(
  "com.twitter" %% "finagle-mysql" % "18.3.0",
  "com.github.finagle" %% "finch-core" % "0.17.0",
  "com.github.finagle" %% "finch-argonaut" % "0.17.0",
  "com.twitter" %% "finagle-http" % "18.3.0",
  "com.github.finagle" %% "finch-circe" % "0.17.0",
  "io.circe" %% "circe-core" % "0.9.1",
  "io.circe" %% "circe-generic" % "0.9.1",
  "ch.qos.logback"  %  "logback-classic"  % "1.1.3"
)

Main.scala
package jp.co.finchitest

import com.twitter.finagle.http.{Request, Response}
import com.twitter.finagle.{Http, Service}
import com.twitter.util.Await
import io.circe.generic.auto._ // *
import io.finch._
import io.finch.circe._ // *
import io.finch.syntax._
import jp.co.finchitest.helpers.MysqlHelper._
import jp.co.finchitest.forms._
import jp.co.finchitest.forms.UserForm._


object Main {

  val listUser: Endpoint[Seq[User]] = get("users") {
    User.all.map{
      case Seq() => NotFound(new Exception("Record Not Found"))
      case users => Ok(users)
    }
  }

  val showUser: Endpoint[User] = get("users" :: path[Long]) {id: Long =>
    User.find(id).map {
      case None => NotFound(new Exception("Record Not Found"))
      case Some(u) => Ok(u)
    }
  }

  val createUser: Endpoint[User] = post("users" :: userReqParams) { p: UserForm =>
    (for {
      id   <- User.create(p.email, p.screen_name)
      user <- User.find(id)
    } yield user) map {
      case Some(u) => Created(u)
      case _ => NotFound(new Exception("Record Not Found"))
    }
  }

  // 配列jsonも出来るかな
  val createUserByJson: Endpoint[Int] = post("usersjson" :: userJson) { p: Seq[UserForm] =>
    val insertedId = p.map(a => User.create(a.email, a.screen_name))
    Ok(insertedId.size)
  }

  val userService: Service[Request, Response] = ( listUser :+: showUser :+: createUser :+: createUserByJson)
    .handle{
      case fe: io.finch.Error => BadRequest(new Exception(fe.getMessage)) // validation Error が起きた場合のcase
      case e: Exception => InternalServerError(new Exception(e.getMessage))
    }
    .toServiceAs[Application.Json]

  def main(args: Array[String]): Unit = {
    Await.ready(Http.serve(":8082", userService))
  }
}
なんか以下のエラーが出た。どうやら、レスポンス時にしっかりとエンコーディングしているかどうかをコンパイル時にチェッックしてくれるらしい。。
error: An Endpoint you're trying to convert into a Finagle service is missing one or more encoders

インポート文を追加したら解消された。
import io.circe.generic.auto._ // *
import io.finch.circe._ // * 
どうやら、implicit def encodeCirce を toServiceAsメソッドに暗黙渡しをしないとダメみだいだ。
Main.scala
  // 配列jsonも出来るかな
  val createUserByJson: Endpoint[Int] = post("usersjson" :: userJson) { p: Seq[UserForm] =>
    val insertedId = p.map(a => User.create(a.email, a.screen_name))
    Ok(insertedId.size)
  }
curl
// 以下のcurlコマンドで、配列jsonも登録できた。
curl -d '[{"email":"eee1@com","screen_name":"test1"},{"email":"eef@ssl","screen_name":"test223"}]' -H "Content-Type: application/json" -X POST http://localhost:8082/usersjson

UserForm.scala
package jp.co.finchitest.forms

import io.finch.{Endpoint, ValidationRule, param}

// formにemail validation機能を付与してみました
case class UserForm(email: String, screen_name: String)
object UserForm {
  val mailRule = ValidationRule[String]("mail should be mailRule")(a => """(\w+)@([\w\.]+)""".r.unapplySeq(a).isDefined)
  val userReqParams:Endpoint[UserForm]= (
      param("email").should(mailRule) ::
      param("screen_name")
    ).as[UserForm]

  val userJson:Endpoint[Seq[UserForm]] = jsonBody[Seq[UserForm]]
}

MysqlHelper.scala
package jp.co.finchitest.helpers

import com.twitter.finagle.Mysql

//WebアプリらしくDB環境周りは独立してみました。
object MysqlHelper {

  implicit val client = Mysql.client
    .withCredentials("root", null)
    .withDatabase("nano_planner_dev")
    .newRichClient("127.0.0.1:3306")
}

User.scala
リンクFinch + MySQLでREST APIサーバを構築する のコードから変えておりません

参考リンク:finchについての情報を一切持ってないので、参考にさせて頂きました。大変助かりました。ありがとうございます。
Finch + MySQLでREST APIサーバを構築する
finch触ってみた
finch公式サイト

4
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?