LoginSignup
0
0

More than 5 years have passed since last update.

Spray: Base64リクエストをデコードしたい

Last updated at Posted at 2015-09-20

SprayでBase64リクエストをデコードする方法を紹介します。

まず、SprayでリクエストボディがBase64のものをデコードするにはいくつかの方法があります。

  1. entity(as[String])で一旦Entityを文字列で受け取り、ルーティングの中でごりごりデコードする
  2. 自前で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関数の型に合致しないため、fromMessageUnmarshallerfromRequestUnmarshallerで型をFromRequestUnmarshaller[T]に変換する必要があります。

Base64Support.scala
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が動く完全なサンプルがあるので、動かしてみたい人はダウンロードしてください。

0
0
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
0
0