§結果の操作
§デフォルトの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
はまだ完全にはサポートされていません。
範囲の結果は、Source
、InputStream
、ファイル、および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)
)
次へ: セッションとフラッシュスコープ
このドキュメントにエラーを見つけましたか?このページのソースコードはこちらにあります。 ドキュメントのガイドラインを読んだら、遠慮なくプルリクエストを提出してください。質問や共有するアドバイスがありますか?コミュニティフォーラムにアクセスして、コミュニティとの会話を始めてください。