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
Proper servant-server exception handling for warp/wai #1192
Comments
In my mind, catching impure exceptions cannot happen in servant without potentially serious performance degradation. Also, it is against the idea that the types represent the behavior of the rest API as completely as possible. I can see two things working:
1 is not always easy, especially if you're using libraries that are sometimes subtle about being patrial; but together with 2., I think it is the way to go. Impure exceptions should be 5xx errors and treated as software bugs. I've now read through #309 and #954 a little, and changed my mind to "it's conceivable that we find a consensus for This is exclusively about impure exceptions, or is that where I'm wrong? |
to re-iterate: we're not talking about having the servant types represent exceptions, but about impure exceptions (ie. the more i think about this, the more i'm certain the solution should be the warp hooks. |
As the author of servant-exceptions, here are my 2cents:
FWIW I drafted a quick example here: https://gist.github.com/ch1bo/cbfff47cd8a8630974c974c46632773c |
This example doesn't use impure exceptions at all. The error here getUser :: MonadThrow m => Text -> m User
getUser n
| n == "foo" = return $ User "foo"
| n == "bar" = error "oops"
| otherwise = throwM UserNotFound has the type | n == "bar" = return $ User $ error "unknown name" which wouldn't be handled by the |
I spent some time reading through issue #309 and the associated discussions in yesodweb/wai#496 and PR #954 about how
servant-server
appears to incorrectly handle exceptions with respect to howwai
/warp
expects to operate.The unfortunate side effect of this behavior is that any uncaught exceptions within a Servant application will not be registered by any
wai
middleware as a 500 exception, which can seriously negatively impact user experience around automated logging, metrics tracking, etc.As far as I can tell, the solution proposed in #309 around deeply evaluating
Response
s intoApplication
before creating aResponseReceived
(to provide towai
) won't work for ensuring that any impure exceptions in thunks are caught (Response
cannot have a validNFData
instance to the best of my knowledg).The machinery for forcing evaluation, catching exceptions, and generating correct
wai
Response
s would have to live somewhere else in Servant, probably using a similar combination of techniques as to what Yesod uses:https://github.com/yesodweb/yesod/blob/6a7370a9e61ca48787c539842602b161c219e6ba/yesod-core/src/Yesod/Core/Internal/Run.hs#L43-L48
https://github.com/yesodweb/yesod/blob/6a7370a9e61ca48787c539842602b161c219e6ba/yesod-core/src/Yesod/Core/Internal/Run.hs#L50-L55
https://github.com/yesodweb/yesod/blob/6a7370a9e61ca48787c539842602b161c219e6ba/yesod-core/src/Yesod/Core/Internal/Run.hs#L104-L130
I'm opening a new issue since it seems as if the old ones have languished a bit, and the strategies for handling this problem outlined in them don't appear to actually address the core issue here.
Does anyone have thoughts on what a good architecture for this might look like?
Perhaps some pointers towards code paths within Servant that would allow us to implement the correct behavior, even just as an opt-in for users who want to ensure that middleware operates as-expected?
The text was updated successfully, but these errors were encountered: