SprayでBase64リクエストをデコードする方法を紹介します。
まず、SprayでリクエストボディがBase64のものをデコードするにはいくつかの方法があります。
-
entity(as[String])
で一旦Entityを文字列で受け取り、ルーティングの中でごりごりデコードする - 自前でBase64をデコードするMarshallerを作る
1の方法は手っ取り早く実装できる反面、Base64デコードの処理を共通化しにくい、デコード失敗のエラーハンドリングをルートごとに書かないと行けないといったデメリットがあります。
今回は2の方法でデコードする方法を紹介します。
Base64のUnmarshallerを作る
Sprayにはリクエストボディを変形するためにUnmarshallingという仕組みが有ります。デフォルトでは、StringやJSON、XMLのUnmarshallerが提供されています。
SprayでJSONを受け取るルートを書くときに、entity(as[???])
のように書きますが、このas[T]
関数がimplicitパラメータで、FromRequestUnmarshaller[T]
を受け取るようになっているため、JSONがデコードできるわけです。
というわけで、Base64にデコードする際には次のようなUnmarshallerインターフェイスを用意しておけば、entity(as[Base64String])
で内部のルートがデコード済みの値を受け取れるようになります。
type Base64String = String
implicit val Base64Unmarshaller: FromRequestUnmarshaller[Base64String] = ???
これをベースに実装したコードが次のものです。Unmarshaller[T]
だと、as
関数の型に合致しないため、fromMessageUnmarshaller
とfromRequestUnmarshaller
で型をFromRequestUnmarshaller[T]
に変換する必要があります。
package playground.spray.example2.marshalling
import java.util.Base64
import spray.http.{ HttpEntity, MediaTypes }
import spray.httpx.unmarshalling.UnmarshallerLifting._
import spray.httpx.unmarshalling._
trait Base64Support {
type Base64String = String
implicit val Base64Unmarshaller: FromRequestUnmarshaller[Base64String] = {
fromRequestUnmarshaller {
fromMessageUnmarshaller {
Unmarshaller[Base64String](MediaTypes.`application/base64`) {
case x: HttpEntity.NonEmpty =>
new String(Base64.getDecoder.decode(x.asString.trim), "UTF-8")
}
}
}
}
}
object Base64Support extends Base64Support
クラス名は、SprayJsonSupport
などにならって、Support
で終わる名前にします。
なお、java.util.Base64
はjava8のAPIなので、java7以下では動きません。java7以下では、Apache CommonsのcodecにBase64のデコーダがあるのでそれを利用することができます。
使用例
上のBase64Support
をルーティングで使う場合は、Base64Support
を継承して使います。
package playground.spray.example2
import playground.spray.example2.marshalling.Base64Support
import spray.routing.HttpService
trait Base64DecodingService extends HttpService with Base64Support {
val decodeRoute = {
entity(as[Base64String]) { body =>
complete(body)
}
}
}
完全なサンプル
GitHubにてBase64Supportが動く完全なサンプルがあるので、動かしてみたい人はダウンロードしてください。