Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Zio HTTP Middleware applies to all combined routes #3502

Open
jwcarvana opened this issue Feb 6, 2024 · 1 comment
Open

Zio HTTP Middleware applies to all combined routes #3502

jwcarvana opened this issue Feb 6, 2024 · 1 comment

Comments

@jwcarvana
Copy link

jwcarvana commented Feb 6, 2024

Tapir version: 1.9.9

Scala version: 2.13.12

When combining multiple HttpApp's when using Tapir's ZioHttpInterpreter().toHttp() middleware ends up applying to NotFound handlers. In the following example, three different HttpApps are combined. Visiting a route that 404's causes the Middleware.requestLogging to print three times. I would expect no log lines since zio.http.Server has its own notFound route handler. This only happens when using Tapir.

object BasicServer extends ZIOAppDefault {
  val index = endpoint.get.in("").out(stringBody).zServerLogic(_ => ZIO.succeed("index"))

  val app1 = ZioHttpInterpreter().toHttp(index) @@ Middleware.requestLogging()

  val hello = endpoint.get.in("hello").out(stringBody).zServerLogic(_ => ZIO.succeed("hello"))

  val app2 = ZioHttpInterpreter().toHttp(hello) @@ Middleware.requestLogging()

  val goodbye = endpoint.get.in("goodbye").out(stringBody).zServerLogic(_ => ZIO.succeed("goodbye"))

  val app3 = ZioHttpInterpreter().toHttp(goodbye) @@ Middleware.requestLogging()

  val run =
    Server.serve(app1 ++ app2 ++ app3).provide(Server.default).exitCode
}

Example project: https://github.com/jwcarvana/notfound-middleware-example

@adamw
Copy link
Member

adamw commented Feb 8, 2024

The zio-http integration has been quirky before, so not sure if something didn't change as to how we should integrate. But I'm no expert on zio-http codebase, so hard to tell.

Interestingly, if we add a purely zio-http endpoint (e.g. Routes(Method.GET / "c" -> handler(Response.text("Hello World!"))).toHttpApp @@ Middleware.requestLogging()), you only get 1 log entry if you invoke /c, but 3 entries if you invoke a non-existent one.

As a work-around, you can interpret multiple endpoints in one go (it's more efficent, as well):

val index = sttp.tapir.endpoint.get.in("").out(stringBody).zServerLogic[Any](_ => ZIO.succeed("index"))
val hello = sttp.tapir.endpoint.get.in("hello").out(stringBody).zServerLogic[Any](_ => ZIO.succeed("hello"))
val goodbye = sttp.tapir.endpoint.get.in("goodbye").out(stringBody).zServerLogic[Any](_ => ZIO.succeed("goodbye"))

val app = ZioHttpInterpreter().toHttp[Any](List(index, hello, goodbye)) @@ Middleware.requestLogging()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants