ドキュメント

§結果の操作

§デフォルトのContent-Typeの変更

結果のコンテンツタイプは、レスポンスボディとして指定するScalaの値から自動的に推測されます。

例えば

val textResult = Ok("Hello World!")

Content-Typeヘッダーをtext/plainに自動的に設定しますが、

val xmlResult = Ok(<message>Hello World!</message>)

Content-Typeヘッダーをapplication/xmlに設定します。

ヒント: これはplay.api.http.ContentTypeOf型クラスを介して行われます。

これは非常に便利ですが、変更したい場合があります。結果に対してas(newContentType)メソッドを使用するだけで、異なるContent-Typeヘッダーを持つ新しい同様の結果を作成できます。

val htmlResult = Ok(<h1>Hello World!</h1>).as("text/html")

または、さらに良いのは、

val htmlResult2 = Ok(<h1>Hello World!</h1>).as(HTML)

注: "text/html"の代わりにHTMLを使用する利点は、文字セットが自動的に処理され、実際のContent-Typeヘッダーがtext/html; charset=utf-8に設定されることです。これについては後ほど説明します

§HTTPヘッダーの操作

結果にHTTPヘッダーを追加(または更新)することもできます。

val result = Ok("Hello World!").withHeaders(CACHE_CONTROL -> "max-age=3600", ETAG -> "xx")

HTTPヘッダーを設定すると、元の結果に存在する場合、前の値が自動的に破棄されることに注意してください。

§クッキーの設定と破棄

CookieはHTTPヘッダーの特別な形式ですが、簡単に使用できるようにヘルパーのセットを提供しています。

次を使用して、HTTPレスポンスにCookieを簡単に追加できます。

val result = Ok("Hello world")
  .withCookies(Cookie("theme", "blue"))
  .bakeCookies()

また、Webブラウザーに以前に保存されたCookieを破棄するには

val result2 = result.discardingCookies(DiscardingCookie("theme"))

同じレスポンスの一部としてクッキーを設定および削除することもできます

val result3 = result.withCookies(Cookie("theme", "blue")).discardingCookies(DiscardingCookie("skin"))

§テキストベースのHTTPレスポンスの文字セットの変更

テキストベースのHTTPレスポンスの場合、文字セットを正しく処理することが非常に重要です。Playはそれを自動的に処理し、デフォルトでutf-8を使用します(utf-8を使用する理由を参照してください)。

文字セットは、テキストレスポンスをネットワークソケット経由で送信する対応するバイトに変換し、適切な;charset=xxx拡張子を使用してContent-Typeヘッダーを更新するために使用されます。

文字セットはplay.api.mvc.Codec型クラスを介して自動的に処理されます。現在のスコープでplay.api.mvc.Codecの暗黙のインスタンスをインポートするだけで、すべての操作で使用される文字セットを変更できます。

class Application @Inject() (cc: ControllerComponents) extends AbstractController(cc) {
  implicit val myCustomCharset: Codec = Codec.javaSupported("iso-8859-1")

  def index = Action {
    Ok(<h1>Hello World!</h1>).as(HTML)
  }
}

ここでは、スコープ内に暗黙の文字セット値があるため、XMLメッセージをISO-8859-1エンコードされたバイトに変換し、text/html; charset=iso-8859-1 Content-Typeヘッダーを生成するためにOk(...)メソッドの両方で使用されます。

さて、HTMLメソッドがどのように機能するのか疑問に思われる場合は、その定義は次のとおりです

def HTML(implicit codec: Codec) = {
  "text/html; charset=" + codec.charset
}

ジェネリックな方法で文字セットを処理する必要がある場合は、APIでも同じことができます。

§Rangeの結果

Playは、範囲リクエストと部分レスポンスの仕組みを定義するRFC 7233の一部をサポートしています。これにより、リクエストに満足のいくRangeヘッダーが存在する場合、206 Partial Contentを提供できます。また、配信されたResultに対してAccept-Ranges: bytesを返します。

注: 複数の範囲をより適切に処理するために一部の解析が行われているという事実を除いて、multipart/byterangesはまだ完全にはサポートされていません。

範囲の結果は、SourceInputStream、ファイル、およびPathに対して生成できます。利用可能なすべてのメソッドについては、RangeResult APIドキュメントを参照してください。例えば

val input          = getInputStream()
val partialContent = RangeResult.ofStream(input, request.headers.get(RANGE), "video.mp4", Some("video/mp4"))

またはSourceの場合

val header  = request.headers.get(RANGE)
val content = "This is the full body!"
val source  = Source.single(ByteString(content))

val partialContent = RangeResult.ofSource(
  entityLength = content.length,
  source = source,
  rangeHeader = header,
  fileName = Some("file.txt"),
  contentType = Some(TEXT)
)

リクエストのRangeが満たされない場合、たとえば、リクエストのRangeヘッダーフィールドの範囲が選択されたリソースの現在の範囲と重複しない場合、HTTPステータス416(範囲を満たせません)が返されます。

また、範囲の結果をより効率的に配信するために、Sourceの特定の場所を事前にシークすることも可能です。これを行うには、事前シークが発生する関数を提供できます

val header  = request.headers.get(RANGE)
val content = "This is the full body!"
val source  = sourceFrom(content)

val partialContent = RangeResult.ofSource(
  entityLength = Some(content.length.toLong),
  getSource = (offset: Long) => (offset, source.drop(offset)),
  rangeHeader = header,
  fileName = Some("file.txt"),
  contentType = Some(TEXT)
)

次へ: セッションとフラッシュスコープ


このドキュメントにエラーを見つけましたか?このページのソースコードはこちらにあります。 ドキュメントのガイドラインを読んだら、遠慮なくプルリクエストを提出してください。質問や共有するアドバイスがありますか?コミュニティフォーラムにアクセスして、コミュニティとの会話を始めてください。