👏

[http4s] Customizing Error Handling の実装

2024/09/06に公開

やりたいこと

Customizing Error Handlingの項がTODOになってたので、備忘録的に残しておく
https://http4s.org/v0.23/docs/error-handling.html#customizing-error-handling

環境

Scala: 3.4.2
http4s: 0.23.27

EmberServerBuilderの実装を確認

EmberServerBuilder に以下の関数が生えている。

def withErrorHandler(
      errorHandler: PartialFunction[Throwable, F[Response[F]]]
  ): EmberServerBuilder[F] =
    copy(errorHandler = errorHandler)

https://http4s.org/v0.23/api/org/http4s/ember/server/EmberServerBuilder.html#withErrorHandler(errorHandler:PartialFunction[Throwable,F[org.http4s.Response[F]]]):org.http4s.ember.server.EmberServerBuilder[F]

使い方

このように、直接 PartialFunction を 渡しても良いし、

EmberServerBuilder
    .default[IO]
    .withHost(ipv4"0.0.0.0")
    .withPort(port"8080")
    .withHttpApp(httpApp)
    .withErrorHandler {
        case e:InvalidMessageBodyFailure => IO(Response(Status.BadRequest))
        case e => IO(Response(Status.InternalServerError))
    
    }
    .build

以下のように別で定義しても良い

def errorHandler: PartialFunction[Throwable, IO[Response[IO]]] = {
  case e: InvalidMessageBodyFailure =>
    for {
      _ <- IO.println(e.getMessage)
      _ <- IO.println(e.getCause.getMessage)
    } yield Response(Status.BadRequest).withEntity(e.getMessage)

  case e =>
    for {
      _ <- IO.println(e.getMessage)
      _ <- IO.println(e.getStackTrace.mkString("\n"))
    } yield Response(Status.InternalServerError).withEntity(e.getMessage)
}

おわり

Discussion