0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

zio-httpは、ZIOベースのHTTPライブラリです。

ルートにミドルウェア設定を適用するためには、@@演算子を使います。
この記事では、以下のサンプルコードを使って、この@@演算子の使い方を解説します。

サンプルコード

import zio._
import zio.http._

object Main extends ZIOAppDefault {
  val app: Routes[Any, Response] = Routes(
    Method.GET / "text" -> handler {
      for {
        _ <- ZIO.sleep(Duration.fromSeconds(1))
      } yield Response.text("Hello World!")
    }
  )

  val middlewares = Middleware.timeout(Duration.fromSeconds(2))

  val run = Server.serve(app @@ middlewares).provide(Server.default)
}

コード解説

ルートの定義

まず、シンプルなルートを定義しています。このルートは、/textへのGETリクエストに対して1秒待ってから"Hello World!"というテキストを返します。

val app: Routes[Any, Response] = Routes(
  Method.GET / "text" -> handler {
    for {
      _ <- ZIO.sleep(Duration.fromSeconds(1))
    } yield Response.text("Hello World!")
  }
)

ミドルウェアの定義

次に、タイムアウトのミドルウェアを定義しています。このミドルウェアは、リクエストが2秒以内に完了しない場合にタイムアウトエラーを返します。

val middlewares = Middleware.timeout(Duration.fromSeconds(2))

@@演算子の使用

最後に、@@演算子を使って、定義したルートにミドルウェアを適用しています。これにより、appのすべてのルートがミドルウェアの影響を受けることになります。

val run = Server.serve(app @@ middlewares).provide(Server.default)

@@演算子の詳細

@@演算子は一見すると何をしているのか分かりにくいかもしれませんが、実態はシンプルで、
Routesクラスの@@メソッドを見てみると、ミドルウェアのapplyメソッドを呼び出しているだけです。

Routesの実装

Routesクラスは、複数のルートを含むデータ構造です。@@演算子は、ミドルウェアをルートに適用するために使われます。

// ZIOの実装から抜粋
final case class Routes[-Env, +Err](routes: Chunk[zio.http.Route[Env, Err]]) { self =>
  private var _tree: Routes.Tree[_] = null.asInstanceOf[Routes.Tree[_]]

  def @@[Env1 <: Env](aspect: Middleware[Env1]): Routes[Env1, Err] =
    aspect(self)
}

Middlewareの実装

Middlewareは、リクエストを処理する前後に追加のロジックを挟むための抽象クラスです。例えば、timeoutは、指定した時間内にリクエストが完了しなければタイムアウトエラーを返します。

// ZIOの実装から抜粋
object Middleware extends HandlerAspects {
  def timeout(duration: Duration)(implicit trace: Trace): Middleware[Any] =
    new Middleware[Any] {
      def apply[Env1 <: Any, Err](routes: Routes[Env1, Err]): Routes[Env1, Err] =
        routes.transform[Env1] { handler =>
          handler.timeoutFail(Response(status = Status.RequestTimeout))(duration)
        }
    }
}

@@演算子の背後では、routes.transformメソッドが呼び出され、各ハンドラにミドルウェアが適用されているだけです。
このシンプルな仕組みにより、@@演算子は直感的かつ柔軟にミドルウェアを適用することができます。

まとめ

zio-http@@演算子を使うことで、ルートに対して簡単にミドルウェアを適用できます。
内部的には、単にroutes.transformを呼び出しているだけでした。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?