Unfilteredでのレスポンスの生成

Unfilteredではunfiltered.request.Responderトレイトをミックスインしたケースクラスやシングルトンを組み合わせてレスポンスの内容(ステータスやヘッダ、ボディ部など)を組み立てます。
たとえば以下のコードではステータスが200、ContentTypeはtext/htmlでHTMLをレスポンスとして返却しています。

def intent = {
  case GET(Path("/")) => 
    Ok ~>                     // ステータス200
    Html(<p>Hello World!</p>) // Content-Type: text/html
}

上記の例でのHtmlは実際には以下のような定義になっており、HtmlContent(ContentTypeとしてtext/htmlをセットする)とResponseString(文字列をレスポンスボディとして返却する)を組み合わせたものであることがわかります。

case class Html(nodes: scala.xml.NodeSeq) extends
  ComposeResponse(HtmlContent ~> ResponseString(nodes.toString))

たとえばXMLを返却したい場合は以下のようにします。

case GET(Path("/xml")) => {
  // 返却するXML
  val xml = <book>
    <title>Seasar2徹底入門</title>
    <author>竹添 直樹</author>
  </book>

  Ok ~>            // ステータスは200
  TextXmlContent~> // Content-Type: text/xml
  ResponseString(xml.toString)
}

レスポンスヘッダを設定するにはヘッダに対応したResponderを使用します。

case POST(Path("/result") & Params(Name(name) & Age(age))) =>
  Ok ~>                       // ステータスは200
  Pragma("no-cache") ~>       // Pragra: no-cache
  CacheControl("no-cache") ~> // Cache-Control: no-cache
  Html(<p>{name} is {age} years old.</p>)

以下のようにしてリダイレクトを行うこともできます。

case GET(Path("/redirect")) => Redirect("/hello")

このように、Unfilteredでは関数を合成することによってクライアントに返却するレスポンスを組み立てていきます。はじめは取っ付きにくいかもしれませんが、慣れてくると独自の関数を作成したり、複数の関数を合成して共通化したりなど、自由にカスタマイズできるようになります。