khrt / Raisin

Raisin - a REST API micro framework for Perl 🐫 🐪
61 stars 29 forks source link

Proposal for a new hook #75

Open lmasarati opened 4 years ago

lmasarati commented 4 years ago

I would find useful to add a new hook to be called in case of failed validation, to allow for modification of headers, content body before a standard 400 Bad Request response is returned. It is clear to me how to add such a hook, but not how to get validation errors that now are logged on STDERR.

lmasarati commented 4 years ago

I propose this pull for the base feature of having a hook specific for failed data validation flow https://github.com/khrt/Raisin/pull/76

khrt commented 4 years ago

Hi @lmasarati, sorry it took that long to reply.

I've checked your PR and I have to reject it, because following this logic Raisin might end up having many-many other different hooks for a lot of other events.

I can think of two possible solutions at the moment, though both of a similar kind:

  1. Do not require a Raisin code change (not tested though should be working) is to add a middleware which would check error code and error message and add headers requested. It requires some kind of heuristics but should be okay in this case.
  2. Extend Raisin's code with adding an additional data structure which will hold information about which hook failed so you can do better detection in 1.
lmasarati commented 4 years ago

Thanks. Part 2 of the solution should be a good start. Developing a custom Middleware would not be a problem if Raisin publishes the result of validation in some environment variables.

lmasarati commented 4 years ago

about hooks in general, there's no way to force an immediate response from inside a hook. For example a custom authorization or authentication could be placed inside the before hook, but in case of failure the request must pass through parameter and route validation before having a chance to be finalized. What about using the hook return value to force a return $res->finalize ?

my $ret = eval {
    $self->hook('before')->($self) and return $res->finalize;

The hook is then responsible for preparing the status, body, headers etc and returning 1 for forcing an immediate response to caller. What do you think?