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

RoutesとHttpRoutes

関数型にエンドポイントを定義します。

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

http4s とは

http4s は Scala 向けの純粋関数型 HTTP ライブラリで、cats-effect と fs2 ストリームを基盤としています。リクエストとレスポンスは不変の値であり、副作用は IO などの多相的なエフェクト型 F[_] に取り込まれます。

サーブレットを変更する代わりに、リクエストからエフェクトを伴う省略可能なレスポンスへの関数として HTTP サービスを記述します。

HttpRoutes 型

中心となる抽象化は HttpRoutes[F] で、Kleisli[OptionT[F, *], Request[F], Response[F]] の別名です。OptionT は、ルートが一致せずレスポンスを返さない場合があることを表します。

このシグネチャを手作業で書くことはほとんどありません。代わりに、HttpRoutes.of コンストラクターと部分関数でルートを構築します。

import cats.effect.IO
import org.http4s._
import org.http4s.dsl.io._

val routes: HttpRoutes[IO] = HttpRoutes.of[IO] {
  case GET -> Root / "hello" => Ok("hi")
}

http4s DSL

DSL のインポート org.http4s.dsl.io._ により、GET、Root、パス区切り文字 / などのパターン抽出子と、Ok や NotFound などのレスポンスビルダーを利用できます。

ルートは PartialFunction[Request[F], F[Response[F]]] です。一致しないケースはそのまま次へフォールスルーします。

import org.http4s.dsl.io._

HttpRoutes.of[IO] {
  case GET -> Root => Ok("root")
  case GET -> Root / "ping" => Ok("pong")
}

パスのマッチング

パスパターンは左から右へ読み取られます。Root は先頭のスラッシュを表し、各 / "segment" は 1 つのリテラルパスセグメントに一致します。

矢印 -> は HTTP メソッドとパスを区切ります。したがって、GET -> Root / "users" は GET /users に一致します。

HttpRoutes.of[IO] {
  case GET -> Root / "users" => Ok("all users")
  case GET -> Root / "users" / "me" => Ok("current user")
}

パス変数

パス内の小文字のバインダーは、そのセグメントを String として取得します。ここでは id が /users/ の後に現れる値を束縛します。

取得されたセグメントは常に文字列です。より豊かな型へのパースは自分で行うか、次に示す抽出子オブジェクトを使用します。

HttpRoutes.of[IO] {
  case GET -> Root / "users" / id =>
    Ok(s"user $id")
}

型付きパス抽出子

http4s には IntVar や LongVar などの抽出子が用意されており、セグメントをその型としてパースできる場合にのみ一致します。数値でないセグメントの場合は、次のケースへフォールスルーします。

UUID のようなドメイン型向けに、unapply を使ったカスタム抽出子も定義できます。

HttpRoutes.of[IO] {
  case GET -> Root / "users" / IntVar(id) =>
    Ok(s"numeric user $id")
}

メソッドのマッチング

-> の前に置くメソッド抽出子には、GET、POST、PUT、DELETE、PATCH などを指定できます。同じパスでもメソッドが異なれば、別々のケースになります。

パスは一致してもメソッドが一致しない場合、http4s は自動的に 405 Method Not Allowed を返します。

HttpRoutes.of[IO] {
  case GET -> Root / "items" => Ok("list")
  case POST -> Root / "items" => Created("made")
  case DELETE -> Root / "items" / IntVar(i) => NoContent()
}

ルートの結合

HttpRoutes[F] は SemigroupK を形成するため、<+> 演算子で複数のルートグループを合成できます。レスポンスを生成した最初のグループが採用されます。

これにより、機能ごとにルートを別々の値へ分割し、1 か所で結合できます。

import cats.syntax.semigroupk._

val all = userRoutes <+> itemRoutes <+> healthRoutes

HttpAppへのルート

サーバーには部分関数ではなく全域関数が必要です。HttpRoutes[F] は .orNotFound によって HttpApp[F] に変換され、一致するルートがない場合に 404 を返します。

HttpApp[F] は Kleisli[F, Request[F], Response[F]] であり、常にレスポンスを返します。

import org.http4s.HttpApp

val app: HttpApp[IO] = routes.orNotFound

Middleware によるラップ

Middleware は HttpRoutes[F] => HttpRoutes[F](または HttpApp に対する関数)です。サービスをラップすることで、ルートのロジックに触れずにロギング、CORS、gzip、認証などを追加できます。

組み込みの例として、org.http4s.server.middleware の Logger、CORS、GZip があります。

import org.http4s.server.middleware.Logger

val logged = Logger.httpApp(logHeaders = true, logBody = false)(app)

ルートでのクエリパラメーター

クエリパラメーターは、QueryParamDecoderMatcher を拡張したマッチャーオブジェクトで照合します。パスパターン内の :? の後に記述します。

存在しない場合があるパラメーターには OptionalQueryParamDecoderMatcher を使用し、Option として取得します。

object NameParam extends QueryParamDecoderMatcher[String]("name")

HttpRoutes.of[IO] {
  case GET -> Root / "hi" :? NameParam(n) => Ok(s"hi $n")
}

理解度チェック

ルートの合成についての理解度を確認します。

まとめ

HttpRoutes.of と DSL でルートを構築し、メソッドとパスを照合し、IntVar とマッチャーで変数を取得し、<+> でグループを合成しました。

ルートは部分関数です。.orNotFound によって全域的な HttpApp になり、Middleware は横断的な関心事のためにサービスをラップします。

よくある質問

「RoutesとHttpRoutes」レッスンは無料ですか?

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

「RoutesとHttpRoutes」で何を学びますか?

関数型にエンドポイントを定義します。 ブラウザで直接実行するハンズオンコードでScala for Backend Engineering & Functional Programmingを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

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

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

「RoutesとHttpRoutes」レッスンにはどのくらい時間がかかりますか?

ほとんどの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に戻る