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

ClassCassException when using HandlerAspect and Path parameters. #3141

Open
Petter-K opened this issue Sep 16, 2024 · 10 comments · May be fixed by #3150
Open

ClassCassException when using HandlerAspect and Path parameters. #3141

Petter-K opened this issue Sep 16, 2024 · 10 comments · May be fixed by #3150
Labels
💎 Bounty bug Something isn't working

Comments

@Petter-K
Copy link
Contributor

Petter-K commented Sep 16, 2024

Describe the bug
We are getting ClassCastExceptions when using a route with Path paramters, and a middleware that adds context.
class zio.http.Request cannot be cast to class scala.Tuple2 (zio.http.Request and scala.Tuple2 are in unnamed module of loader 'app')
Tuple2 is increasing if we add more path params

To Reproduce
Run this snipped

import zio.http._
import zio._

import scala.annotation.nowarn

object Reproducer extends ZIOAppDefault {
  case class WebSession(id: Int)

  def maybeWebSession: HandlerAspect[Any, Option[WebSession]] =
    HandlerAspect.interceptIncomingHandler(
      Handler.fromFunctionZIO[Request] { req =>
        ZIO.succeed((req, None))
      }
    )

  @nowarn("msg=dead code following this construct")
  override def run: ZIO[Any, Any, Any] = {
    // fails at Handler.scala line 57 with 
    val route = Method.GET / "base" / string("1") -> handler((a: String, req: Request) => {
      withContext((c: Option[WebSession]) => {
        ZIO.logInfo("Hello").as(Response.ok)
      })
    }) @@ maybeWebSession



    (for {
      port <- Server.install(Routes(route))
      _ <- ZIO.logInfo(s"Installed on port " + port)
      _ <- ZIO.never
    } yield ()).provide(Server.default)

  }
}

run: curl -v 127.0.0.1:8080/base/1

Expected behaviour
Log Hello and return 200 Ok

Additional context
Same error in scala 2 and 3.
Using Intellij breakpoints on all exception, it stops at Handler.scala - line 57

@Petter-K Petter-K added the bug Something isn't working label Sep 16, 2024
@jdegoes
Copy link
Member

jdegoes commented Sep 18, 2024

/bounty $150 for fix and test case.

Copy link

algora-pbc bot commented Sep 18, 2024

💎 $150 bounty • ZIO

Steps to solve:

  1. Start working: Comment /attempt #3141 with your implementation plan
  2. Submit work: Create a pull request including /claim #3141 in the PR body to claim the bounty
  3. Receive payment: 100% of the bounty is received 2-5 days post-reward. Make sure you are eligible for payouts

Thank you for contributing to zio/zio-http!

Add a bountyShare on socials

Attempt Started (GMT+0) Solution
🔴 @varshith257 Sep 18, 2024, 1:46:20 PM WIP
🟢 @987Nabil #3150

@varshith257
Copy link
Contributor

varshith257 commented Sep 18, 2024

/attempt #3141

Algora profile Completed bounties Tech Active attempts Options
@varshith257    4 ZIO bounties
+ 9 bounties from 6 projects
TypeScript, Go
Cancel attempt

Copy link

algora-pbc bot commented Sep 18, 2024

💡 @987Nabil submitted a pull request that claims the bounty. You can visit your bounty board to reward.

987Nabil added a commit to 987Nabil/zio-http that referenced this issue Sep 20, 2024
Copy link

algora-pbc bot commented Sep 25, 2024

@varshith257: Reminder that in 7 days the bounty will become up for grabs, so please submit a pull request before then 🙏

Copy link

algora-pbc bot commented Oct 2, 2024

The bounty is up for grabs! Everyone is welcome to /attempt #3141 🙌

@Petter-K
Copy link
Contributor Author

Petter-K commented Oct 3, 2024

Any update on this?

@987Nabil
Copy link
Contributor

987Nabil commented Oct 4, 2024

I have a proposal. But it is breaking. I want to take a look agin together with @jdegoes

@sullivan-
Copy link
Contributor

sullivan- commented Dec 11, 2024

I took a quick look at the PR. Am I right in thinking that we are trying to convert a runtime ClassCastException into a compiler error? Of course it would be better to have a compile time error, but I think there is a bigger question -- Why can't HandlerAspects be usable for Handlers with inputs such as (String, Request)? These kinds of handlers are the handlers we are supposed to use with the path codecs.

As it is, it seems impossible for me to combine my authentication HandlerAspect with a PathCodec.string. This seems like a very serious limitation. Unless there is some workaround I am not aware of?

Maybe it would make more sense to stick the path codecs into the R of a Handler[-R, +Err, -In, +Out] somehow rather than into the In?

@sullivan-
Copy link
Contributor

FWIW here is my failing case. it gives the same ClassCastException:

object ChallengeSpec extends ZIOSpecDefault:

  def handleMessage(message: String, request: Request): ZIO[Int, Response, Response] =
    ZIO.service[Int].map(i => Response.text(s"$message $i"))

  val authenticationAspect: HandlerAspect[Any, Int] =
    HandlerAspect.interceptIncomingHandler(Handler.fromFunction[Request] { request =>
      (request, 7)
    })

  val routes = Routes(
    Method.DELETE / string("message") -> handler(handleMessage) @@ authenticationAspect
  )

  def spec = test("handler should route") {
    for
      response <- routes.runZIO(Request.delete(URL(root) / "twenty"))
      body <- response.body.asString
    yield
      assert(response.status)(equalTo(Status.Ok)) &&
      assert(body)(equalTo("twenty 7"))
  }

It seems I have two paths forward: Either rewrite HandlerAspect to have looser type params (seems an incredibly hard prospect for me), or rewrite my authentication code to no longer be an aspect.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
💎 Bounty bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants