Scala用のREST APIフレームワークResty 0.0.5をリリースしました

Scala用の超シンプルなREST APIフレームワークとしてRestyというものを作っています。

takezoe.hatenablog.com

github.com

前回ブログで書いてからちょこちょこいじりつつバージョンアップを重ねているので、前回のブログで紹介できなかった機能や、これまでに新たに追加した機能について簡単にまとめてみたいと思います。

全自動Zipkin

Restyはもともと全自動でSwagger、Hystrixと連携する機能を備えていましたが、これに加えてZipkinも全自動で利用できるようになりました。

以下のようにコントローラーにHttpClientSupportというトレイトをミックスインし、このトレイトが提供するメソッドを使用して別サービスの呼び出しを行うことでZipkinでトレースを行うことができます。

class HelloController extends HttpClientSupport {
  @Action(method = "GET", path = "/hello/{id}")
  def hello(id: Int): Message = {
    // Call other API using methods provided by HttpClientSupport
    val user = httpGet[User](s"http://localhost:8080/user/${id}")
    Message(s"Hello ${user.name}!")
  }
}

なお、全自動と言いつつweb.xmlで少しだけ設定が必要です。Zipkinインテグレーションを使用するかどうか、サンプリングレート、ZipkinサーバのURLを指定します。

<context-param>
  <param-name>resty.zipkin</param-name>
  <param-value>enable</param-value>
</context-param>
<context-param>
  <param-name>resty.zipkin.sample.rate</param-name>
  <param-value>1.0</param-value>
</context-param>
<context-param>
  <param-name>resty.zipkin.server.url</param-name>
  <param-value>http://127.0.0.1:9411/api/v1/spans</param-value>
</context-param>

web.xmlでの設定

全自動SwaggerやHystrixが使えるのは便利なのですが、セキュリティ上運用時はエンドポイントを無効にしたいというケースもあるはずなのでweb.xmlで設定できるようにしました。

どちらもデフォルトでは無効になっており、web.xmlに以下の設定を追加することで有効になります。

<context-param>
  <param-name>resty.swagger</param-name>
  <param-value>enable</param-value>
</context-param>

<context-param>
  <param-name>resty.hystrix</param-name>
  <param-value>enable</param-value>
</context-param>

今後はもう少し設定可能なパラメータを増やしていこうと思っています。

ケースクラスのバリデーション

JSONマッピングするケースクラスのコンストラクタでassertすることで入力値のバリデーションができるようになりました。

case class Message(message: String){
  assert(message.length < 10, "message must be less than 10 charactors.")
}

以下のようなレスポンスが400 BadRequestステータスで返却されます。

{
  "errors": [
    "message must be less than 10 charactors."
  ]
}

もう少し本格的なバリデーションフレームワークを入れようかなとも思ったのですが、Restyはシンプル第一なので標準機能としてはこのくらいにしておこうと思います。

ServletAPIへのアクセス

Restyのコントローラーは基本的にServlet API非依存ですが、Restyが提供する機能だけでは不可能な細かい処理を行う必要がある場合や、HttpSessionを使用したい場合など、Servlet APIを使う必要がある場合はコントローラーにServletAPIトレイトをミックスインするとrequestresponseHttpServletRequestHttpServletResponseにアクセスできるようになります。

class HelloController extends ServletAPI {
  @Action(method = "GET", path = "/hello")
  def hello(): Message = {
    val name = request.getParameter("name")
    Message(s"Hello ${name}!")
  }
}

まとめ

Restyは関数型プログラミングや非同期処理の知識がなくてもScalaで簡単にJSONベースのREST APIを実装することができます。サンプルプロジェクトから始めるのが手っ取り早いと思いますので興味のある方は是非試してみていただければと思います。

github.com