Skip to content

HandlerAspect and Routes Env does not compose properly on Scala 2 #3231

@jgranstrom

Description

@jgranstrom

Describe the bug
HandlerAspect and Routes environment still does not compose properly on Scala 2. There's a previous (closed) issue on it here #3112, but it is not resolved. Feel free to close this and re-open that if that would be more useful.

To Reproduce
Using an example in the repo (sbt zioHttpExample/compile):

--- a/zio-http-example/src/main/scala/example/middleware/CustomAuthProviding.scala
+++ b/zio-http-example/src/main/scala/example/middleware/CustomAuthProviding.scala
@@ -8,10 +8,11 @@ import zio.http.codec.PathCodec.string

 object CustomAuthProviding extends ZIOAppDefault {

+  class AuthService
   final case class AuthContext(value: String)

   // Provides an AuthContext to the request handler
-  val provideContext: HandlerAspect[Any, AuthContext] = HandlerAspect.customAuthProviding[AuthContext] { r =>
+  val provideContext: HandlerAspect[AuthService, AuthContext] = HandlerAspect.customAuthProviding[AuthContext] { r =>
     {
       r.headers.get(Header.Authorization).flatMap {
         case Header.Authorization.Basic(uname, password) if Secret(uname.reverse) == password =>
@@ -24,18 +25,13 @@ object CustomAuthProviding extends ZIOAppDefault {
   }

   // Multiple routes that require an AuthContext via withContext
-  val secureRoutes: Routes[AuthContext, Response] = Routes(
+  val secureRoutes: Routes[AuthContext with AuthService, Response] = Routes(
     Method.GET / "a" -> handler((_: Request) => withContext((ctx: AuthContext) => Response.text(ctx.value))),
-    Method.GET / "b" / int("id")      -> handler((id: Int, _: Request) =>
-      withContext((ctx: AuthContext) => Response.text(s"for id: $id: ${ctx.value}")),
-    ),
-    Method.GET / "c" / string("name") -> handler((name: String, _: Request) =>
-      withContext((ctx: AuthContext) => Response.text(s"for name: $name: ${ctx.value}")),
-    ),
   )

-  val app: Routes[Any, Response] = secureRoutes @@ provideContext
+  val app: Routes[AuthService, Response] = secureRoutes @@ provideContext                  // <--- Does not compile
+  // val app: Routes[AuthService, Response] = secureRoutes @@[AuthService] provideContext  // <--- Compiles

-  val run = Server.serve(app).provide(Server.default)
+  val someAuthService = new AuthService()
+  val run = Server.serve(app).provide(Server.default, ZLayer.succeed(someAuthService))

 }

Compiler error on inference is:

[info] compiling 1 Scala source to /Users/johngranstrom/code/zio-http/zio-http-example/target/scala-2.13/classes ...
[error] /Users/johngranstrom/code/zio-http/zio-http-example/src/main/scala/example/middleware/CustomAuthProviding.scala:32:57: inferred type arguments [example.middleware.CustomAuthProviding.AuthService,example.middleware.CustomAuthProviding.AuthContext] do not conform to method @@'s type parameter bounds [Env0,Ctx <: example.middleware.CustomAuthProviding.AuthContext with example.middleware.CustomAuthProviding.AuthService]
[error]   val app: Routes[AuthService, Response] = secureRoutes @@ provideContext
[error]                                                         ^
[error] /Users/johngranstrom/code/zio-http/zio-http-example/src/main/scala/example/middleware/CustomAuthProviding.scala:32:60: type mismatch;
[error]  found   : zio.http.HandlerAspect[example.middleware.CustomAuthProviding.AuthService,example.middleware.CustomAuthProviding.AuthContext]
[error]  required: zio.http.HandlerAspect[Env0,Ctx]
[error]   val app: Routes[AuthService, Response] = secureRoutes @@ provideContext

Expected behaviour
For this to be inferred. And otherwise we need to at least document this requirement

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions