Scala for Backend Engineering & Functional Programming · レッスン

リクエストとレスポンス

入力を読み取り、出力を返します。

レッスン 2/413 ステップ

「リクエストとレスポンス」はCoddyKit上の無料Scala for Backend Engineering & Functional Programmingレッスンです。 これはレッスン2/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはScala for Backend Engineering & Functional Programming学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。

値としてのリクエスト

http4s の Request[F] は、メソッド、URI、ヘッダー、HTTP バージョン、ストリーミングボディを持つ不変の値です。純粋なアクセサーで調べられ、直接変更することはありません。

リクエストを変更するには、withHeaders、withUri などのコンビネーターでコピーを生成します。

val r: Request[IO] = Request[IO](
  method = Method.GET,
  uri = uri"/health"
)

ストリーミングボディ

リクエストまたはレスポンスのボディは fs2.Stream[F, Byte] です。遅延的かつエフェクトを伴って消費されるため、大きなペイロード全体をメモリ上に保持する必要がありません。

通常は生のバイト列を直接扱わず、EntityDecoder にデコードを任せます。

// raw access (rarely needed)
val bytes: fs2.Stream[IO, Byte] = request.body

ボディのデコード

EntityDecoder[F, A] は、ボディストリームを A に変換する方法を知っています。req.as[A] を呼び出してデコードすると F[A] が返され、ボディが不正な場合はエフェクトが失敗します。

String 用の組み込みデコーダーがあり、より豊かな型向けのものは JSON モジュールから提供されます。

HttpRoutes.of[IO] {
  case req @ POST -> Root / "echo" =>
    req.as[String].flatMap(body => Ok(body))
}

リクエストを束縛する

ケース内でリクエストオブジェクトにアクセスするには、@ で束縛します。ここでは req がリクエスト全体を指し、パターンではメソッドとパスのマッチングも続けて行います。

バインダーがなければ分解された各部分しか利用できず、ボディやヘッダーを読み取れません。

HttpRoutes.of[IO] {
  case req @ PUT -> Root / "name" =>
    req.as[String].flatMap(n => Ok(s"set $n"))
}

ヘッダーの読み取り

ヘッダーは request.headers にあります。型付きヘッダーモデルには headers.get[H] を使用し、任意の名前には headers.get(CIString("X-Custom")) を使用します。

Authorization や Content-Type などの型付きヘッダーは、値のパースと検証を自動的に行います。

import org.http4s.headers.Authorization

val auth: Option[Authorization] =
  request.headers.get[Authorization]

レスポンスの構築

Ok、Created、NotFound などの DSL レスポンスビルダーは、F[Response[F]] を返す関数です。引数を渡すと、EntityEncoder によってボディが設定されます。

各ビルダーはステータスコードに対応しているため、Created(...) は 201 を返します。

Ok("all good")          // 200
Created("made it")      // 201
NotFound("missing")     // 404

ステータスコードを直接指定する

便利なビルダーがないステータスを使う場合やカスタマイズする場合は、明示的な Status を指定して Response[F] を構築し、withEntity をチェーンします。

これにより、ステータス、ヘッダー、ボディを 1 つの式で完全に制御できます。

import org.http4s.{Response, Status}

Response[IO](Status.Accepted)
  .withEntity("queued")
  .pure[IO]

ボディのエンコード

EntityEncoder[F, A] は値をレスポンスボディにシリアライズし、Content-Type を設定します。String とバイト列のエンコーダーは組み込みで、JSON のエンコーダーは circe から提供されます。

Ok(value) に値を渡すと、http4s はエンコーダーを implicit に検索します。

// String encoder is implicit; sets text/plain
val resp: IO[Response[IO]] = Ok("plain text body")

レスポンスヘッダーの設定

ヘッダーはビルダーに追加の引数として渡すか、レスポンスのエフェクトに .map(_.putHeaders(...)) をチェーンして追加します。

型付きヘッダーモデルにより、たとえば 201 Created の Location ヘッダーなど、値を正しい形式で設定できます。

import org.http4s.headers.Location

Created("ok").map(_.putHeaders(
  Location(uri"/items/42")
))

デコード失敗の処理

ボディをデコードできない場合、req.as[A] は F エフェクトを失敗させます。req.attemptAs[A].value を使うと F[Either[DecodeFailure, A]] を取得でき、左側の場合に 400 を返せます。

これにより、不正な入力の処理を明示的かつ全域的に保てます。

req.attemptAs[String].value.flatMap {
  case Right(b) => Ok(b)
  case Left(_)  => BadRequest("bad body")
}

Cookie とリダイレクト

response.addCookie(ResponseCookie(name, value)) で Cookie を設定します。リダイレクトには 3xx ビルダーと Location ヘッダーを使用します。

SeeOther(Location(uri)) は 303 を返す、慣用的な post-redirect-get のレスポンスです。

import org.http4s.headers.Location

SeeOther(Location(uri"/login"))
  .map(_.addCookie("sid", "abc123"))

理解度チェック

安全なボディのデコードについて考えます。

まとめ

リクエストとレスポンスは、ストリーミングする fs2 ボディを持つ不変値です。EntityDecoderを介してas/attemptAsでデコードし、EntityEncoderでエンコードします。

ビルダーでステータスコードを設定でき、型付きヘッダーによって安全性が保たれます。Cookieやリダイレクトも、単なるレスポンス変換として扱えます。

無料で開始

AI チューターと学ぶ Scala — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
39
レッスン
143

よくある質問

「リクエストとレスポンス」レッスンは無料ですか?

はい。「リクエストとレスポンス」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Scala for Backend Engineering & Functional Programmingコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Scala for Backend Engineering & Functional Programmingコースには全4レッスンが含まれています。

「リクエストとレスポンス」で何を学びますか?

入力を読み取り、出力を返します。 ブラウザで直接実行するハンズオンコードでScala for Backend Engineering & Functional Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Scala for Backend Engineering & Functional Programmingを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのScala for Backend Engineering & Functional Programmingは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン2/4です。

「リクエストとレスポンス」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このScala for Backend Engineering & Functional Programmingレッスンでコードを書いて実行できますか?

はい。すべてのScala for Backend Engineering & Functional Programmingレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. RoutesとHttpRoutes
  2. リクエストとレスポンス
  3. JSONエンドポイント
  4. アプリケーションを提供する
← Scala for Backend Engineering & Functional Programmingに戻る