error handler
I would like to be able to define what happens to internal server errors. Currently they return a 500 with the full stack trace, I want to not show the stack trace for example.
Accepted
I did check that this worked as expected:
["/500" (resource
{:methods {:get {:produces "text/html"
:response (fn [ctx] (throw (new Exception "Ooh!")))}}
:responses {500 {:produces "text/plain"
:response (fn [ctx] "Error, but I'm OK")}}}
)]
Is this enough for your purposes?
Ah-ha! I think I was trying to use :responses within the :method my
apologies. This is exactly what I need. The only thing I would add though
is that for an HTTP server, a dumbed down error response might be required
globally. For a public API you don't really want to expose information
about the server that can come from a stack trace, I know yada tries to
avoid this type of global requirement but shouldn't this be a special case?
Or alternatively the default error handler should not send back stack
traces...
On Mon, Feb 8, 2016 at 4:40 PM, Malcolm Sparks [email protected] wrote:
I did check that this worked as expected:
["/500" (resource {:methods {:get {:produces "text/html" :response (fn [ctx](throw %28new Exception)))}} :responses {500 {:produces "text/plain" :response (fn [ctx] "Error, but I'm OK")}}} )]
Is this enough for your purposes?
— Reply to this email directly or view it on GitHub https://github.com/juxt/yada/issues/55#issuecomment-181416338.
It might be useful to be able to put :responses inside :method.
I'd yada to do the right thing in both dev and prod cases, but without requiring a configuration step (the way that pedestal needs a bootstrap config).
Perhaps an environment variable could be used in prod which yada's handler could pick up. I don't really want to go down the route of giving handler's options again. Eventually I hope that the default exceptions are really useful for developers (not just stack traces, but an entire story of the request and suggestions of how to fix the issue). It tends to be in prod that you get to set environment variables.
Have you got any further thoughts on this strategy?
not really, it is really dev vs prod for the default handler. I just think that it's too easy not deploy this error handling to prod and not define a 500.
For me, the example by @malcolmsparks above only works with instances of ExceptionInfo, ie something thrown using ex-info, not other Throwables. Using yada 1.1.6.
Ah, in that case this is an issue - let's keep it open
To be more specific, the example above doesn't work for :post methods:
(yada/yada
(yada/resource
{:methods
{:post {:consumes "application/json"
:produces "text/plain"
:response (λ [ctx] (throw (Exception. "Oh!")))}}
:responses
{500 {:produces "text/plain"
:response (λ [ctx] "Internal error")}}}))
-> the "Internal error" is not shown, instead you get the full stacktrace.
Today I was googling for yada exception handling and I clicked through on one of the links:
Once our API's/HTTP servers/whatever it it that we're developing are public facing, it's desirable to put a facade on our oversights (i.e. a nice "oops, we made a boo boo" page), and so I think it would make sense to have a generic server error response. I understand this is WIP, which is great.
For the time being, is using :responses something which can be used in the interim, and simply walking the tree that is my bidi routes, and inserting my default error handler for all resources which don't already have one defined?
Thanks a lot for a great library.
Yes, that's exactly the purpose of status responses: https://juxt.pro/yada/manual/index.html#status-responses
The code in yada that supports this feature is somewhat of a placeholder, and if you have any particular requirements that aren't possible yet I'd be very happy to provide improvements - let me know what you need.
Malcolm Sparks Director
Email: [email protected] Web: https://juxt.pro
JUXT LTD. Software Consulting, Delivery, Training
On 19 August 2016 at 17:38, Marcin Jekot [email protected] wrote:
Today I was googling for yada exception handling and I clicked through on one of the links:
[image: screen shot 2016-08-19 at 18 25 29] https://cloud.githubusercontent.com/assets/514563/17816695/d4001bbe-663a-11e6-972f-75dc60c696c4.png
Once our API's/HTTP servers/whatever it it that we're developing are public facing, it's desirable to put a facade on our oversights (i.e. a nice "oops, we made a boo boo" page), and so I think it would make sense to have a generic server error response. I understand this is WIP, which is great.
For the time being, is using :responses something which can be used in the interim, and simply walking the tree that is my bidi routes, and inserting my default error handler for all resources which don't already have one defined?
Thanks a lot for a great library.
— You are receiving this because you were mentioned. Reply to this email directly, view it on GitHub https://github.com/juxt/yada/issues/55#issuecomment-241068451, or mute the thread https://github.com/notifications/unsubscribe-auth/AAJ9Owy-vTJ9JLbmHuDnurStqRGnitwxks5qhdv4gaJpZM4HTklr .
Thanks @malcolmsparks.
I have 2 specific use cases, one is being able to define a generic 5xx error page for all routes, or a certain sub-set. And as described above, it would be useful to be able to toggle the stack trace off and on given either prod, or a non-prod setup.
The second one: we are trying to capture and send all 5xx errors to Bugsnag. I am not sure if this is currently possible, but is there an interceptor chain equivalent on the response? How would one go about defining a generic error handler, which would then forward all exceptions, as well as the ctx to bugsnag.
Come to think of it, use case 1 and 2 could possibly be addressed using the same strategy?
I've built quite a few APIs with yada and the error handling is always a bit odd. Let me describe a bit in detail first the use case and then what I think the problem is.
Use case
Usually the API resources will call some function in a business 'layer'. Errors can be thrown here and do not necessarily know about http status codes. Take as an example e.g. a Datomic Cloud system that throws ExceptionInfo with Cognitect Anomalies error categories, but this will be true for any business logic / database system.
If you do not catch these errors in your :properties or :response methods, they will get translated into internal server errors. Fine so far.
Now, if you do want to turn these errors into something that the HTTP client might react upon, you need some translation mechanism and generate proper status codes. The purpose is to have standardized errors sent to the HTTP client, with a body that can be read programmatically.
There are a couple of options for this in yada right now:
- catch exceptions everywhere they can occur (properties, authorization, methods, ...) and translate them into a proper HTTP status. This will have error handling code all over the place and all you want to do is have a
::anomalies/forbiddengenerate a 403. - use the
:responsesmechanism to translate the error right before sending it back to the client. This will however still treat the error as an Internal Server Error in yada (i.e. print logs) - walk the bidi tree and update the necessary functions (probably
:propertiesand:responseof each method) to wrap with the error handler.
Problems
1. Generic error handler
There is no mechanism for passing an error handler to a resource. Currently there is a default error handler defined in yada.handler. This is however not an error handler, but a logger. Would it be an option to have an error handler either translate the error into a valid next context or throw an error? A bit the same as an error-handler works on core.async channels. One question that I'm still struggling with is, does this even make sense? E.g. an error occurring during authentication might still have a completely different format/meaning than an error happening during the method call. Other thoughts appreciated.
2. Error interceptor chain does not receive updated context
In case of an error, the error interceptor chain does not receive the ctx as it has been updated so far. This is due to catching only the original context. This removes e.g. an authenticated user from the context, which might be useful information for logging etc. Not sure how to capture the updated context here, but it needs to interleave the normal interceptor chain with the catch blocks or something.
3. Yada error format specification
When yada generates an error (e.g. for validating query parameters) it generates something of the form of {:errors [["query" {:error {:object "missing-required-key"}}]]}. Is this format described somewhere? If we want to have error bodies read programmatically, it needs to be the same format for yada errors as other 'functional' errors. It's possible to translate a yada error into the agreed format for clients, but how do we detect it is a yada generated error?