zio / zio-http

A next-generation Scala framework for building scalable, correct, and efficient HTTP clients and servers
https://zio.dev/zio-http
Apache License 2.0
800 stars 403 forks source link

Using a handled route with error handling functions causes a ClassCastException #3134

Closed mschuwalow closed 1 month ago

mschuwalow commented 2 months ago

Describe the bug

Affected versions: 3.0.0-RC5+ including 3.0.0

This pr introduced changes to the error handling behaviour, allowing error handling functions to be used together with routes that don't fail / use the failure channel for responses.

Problem is that the type signature lies for handled handlers. A Handled route will not fail with a Cause[Nothing], but rather with a Cause[Response]. This can cause ClassCastExceptions at runtime.

For example trying to use .handleErrorCauseZIO(c => ZIO.logInfo(Try(c.squash).toString()).as(Response.ok)) with a handled route will log a class zio.http.Response cannot be cast to class scala.runtime.Nothing$.

Root cause are this line which casts the cause to a Cause[Nothing].

And this constructor of a Route using a RoutePattern and a handled handler. This function has an unused type parameter [Err] with ends up being Nothing unless explicitly specified.

To Reproduce Steps to reproduce the behaviour:

  1. Create a simple zio-http application:
    
    package example

import zio. import zio.http. import scala.util.Try

object Main extends ZIOAppDefault {

val routes = Routes( Method.GET / "foo" -> handler { _: Request => ZIO.fail(Response.ok) } ).handleErrorCauseZIO(c => ZIO.logInfo(Try(c.squash).toString()).as(Response.ok))

def run: ZIO[Environment with ZIOAppArgs with Scope,Any,Any] = Server.serve(routes).provideLayer(Server.default)

}


2. Run it
3. Send a http get request to http://localhost:8080/foo
4. See error in the logs

**Expected behaviour**
No Classcast exceptions should happen at runtime. I suspect one of two solutions would fit here:
1. Error type of handled routes should be Cause[Response] not Cause[Nothing].
2. When using error handling operators on Handled routes we should strip all failures and only leave interrupts and defects to be logged. IMO this has better ergonomics than options (1) and is what I would prefer here.

**Additional Notes**

Looks like this issue was already reported here https://github.com/zio/zio-http/issues/2580#issuecomment-2139543267
jdegoes commented 2 months ago

/bounty $125 for fix and test case (may be duplicate).

algora-pbc[bot] commented 2 months ago

💎 $125 bounty • ZIO

Steps to solve:

  1. Start working: Comment /attempt #3134 with your implementation plan
  2. Submit work: Create a pull request including /claim #3134 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 bounty • Share on socials

Attempt Started (GMT+0) Solution
🟢 @mschuwalow Sep 18, 2024, 2:47:21 PM #3146
mschuwalow commented 2 months ago

/attempt #3134

Algora profile Completed bounties Tech Active attempts Options
@mschuwalow 1 ZIO bounty
Scala, TypeScript,
Nix & more
Cancel attempt
algora-pbc[bot] commented 2 months ago

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

algora-pbc[bot] commented 1 month ago

🎉🎈 @mschuwalow has been awarded $125! 🎈🎊