rho icon indicating copy to clipboard operation
rho copied to clipboard

Customizable Error Messages

Open zarthross opened this issue 7 years ago • 4 comments

I have a requirement for my APIs where all messages are in JSON format.

Rho has several places where error messages are hard coded. I would prefer if users can specify their own error messages so they can be JSON, ProtoBuf, XML, Japanese, or whatever a user might need.

To list a few: (Line numbers based on tag v0.18.0-M1 instead of master for stability)

  • [ ] PathTree.scala line 263
  • [ ] QueryParser.scala lines 76 and 80
  • [ ] StringParser.scala line 21 31 (A few more because of DateTime parser branch merge)
  • [ ] package.scala line 71, 81, 91, 101, 183, 259, and 264

I would LOVE to submit a PR to make this easier, but would like to discuss what the best path is to make this more usable.

The way I see it is we have 2 choices...

  1. Overrides
  • Just override all the implicits with ones that respect the format of error messages I want
  • Make _captureMapR in package.scala protected so i can override it when I inherit from RhoDSL
  1. Typeclasses
  • Make a error type class for Paths, Headers, QueryParams with an sealed class hierarchy of error types and have a default implicit function that gives the existing error messages.
  • Require param, capture +?, etc to take an implicit error handler of sorts.

I prefer path 2, but want some suggestions before I get start on this.

zarthross avatar Feb 11 '18 16:02 zarthross

I would favor option 2 as well. Implicits in the project already are taken to its extreme, and adding more overrides could makes things harder to understand, specially when they go wrong.

jcranky avatar Feb 12 '18 12:02 jcranky

Hello Have you considered using the org.http4s.ServiceErrorHandler? It's how http4s lets users override responses for errors. It also provides nice logging of errors by default, which I miss every time rho hits me with "The request body was malformed." and no details or logs. It may not be as fine-grained approach as typeclasses, but it seems to be enough to satisfy the need to provide custom error responses and has the advantage of being compatible with http4s (important when mixing http4s and rho services).

RafalSumislawski avatar Nov 11 '18 16:11 RafalSumislawski

@RafalSumislawski The ServiceErrorHandler can still be used with Rho, but it only triggers if there is an exception. In many places it isn't an exception, but some validation that fails. Moreover, what I want is something that gets more granular detail about the failure, so it can't quite be as generic.

zarthross avatar Apr 09 '19 18:04 zarthross

If I can add my 2 cents about handling errors with ServiceErrorHandler and rho, I find a bit tricky.

For example this exception will be handled by ServiceErrorHandler:

  "Example" **
    GET / "example"  |>> {
     IO(throw new RuntimeException("Boom!")) *>
       IO(Ok())
   }

But this one not:

  "Example" **
    GET / "example"  |>> {
     throw new RuntimeException("Boom!")
     Ok()
   }

It would be caught and logged in PathTree.scala#136

I don't know if that is a design decision or not, but currently one needs to be very careful in the routes code.

mgibowski avatar Nov 19 '19 15:11 mgibowski