我有一个项目有两个部分:
我在errorHandler
实例声明中使用Yesod
函数在出现问题时为网页构建错误页面。
然而,API中的所有路由都会创建JSON
个响应。我使用runInputPost
生成处理API输入的输入表单。使用缺少的参数调用API时,Yesod会生成InvalidArgs
异常,并返回错误HTML页面。
我希望能够处理该异常并返回JSON
,例如:
{
"success" : False,
"code" : 101,
"message" : "The argument 'blabla' was missing"
}
如果不创建具有自己的errorHandler
的子网站,我该怎么做?
答案 0 :(得分:1)
在阅读了有关如何捕获monad堆栈(here和here)中发生的异常之后,我发现了一些似乎易于使用的库exceptions
。
我读到了实现Yesod
类型类的Exception
中的哪个类型,结果发现它是一个名为HandlerContents
的类型:
data HandlerContents =
HCContent H.Status !TypedContent
| HCError ErrorResponse
| HCSendFile ContentType FilePath (Maybe FilePart)
| HCRedirect H.Status Text
| HCCreated Text
| HCWai W.Response
| HCWaiApp W.Application
deriving Typeable
我对HCError
感兴趣,因为它包含ErrorResponse
(与errorHandler
相同的类型)。
我在我的cabal文件中将exceptions
库添加到build-depends
。我在API中的所有处理程序都有签名:: Handler Value
所以我创建了一个名为catchRouteError
的实用程序函数,我可以运行我的处理程序:
catchRouteError :: Handler Value -> Handler Value
catchRouteError r = catch r handleError
where
handleError :: HandlerContents -> Handler Value
handleError (HCError (InvalidArgs _)) = ... create specific json error
handleError (HCError _) = ... create generic json error
handleError e = throwM e
由于HandlerContents
用于其他方面,例如重定向和接收文件,我只匹配HCError
并让默认实现处理其他所有内容。
现在我可以使用此功能轻松运行我的处理程序:
postAPIAppStatusR :: Handler Value
postAPIAppStatusR = catchRouteError $ do
...
这是我的问题的快速解决方案,我确信有更优雅的解决方案,具有更好Yesod
知识的人可以提供。
答案 1 :(得分:1)
虽然您的解决方案确实有效,但您可以改为使用runInputPostResult函数,该函数实际上是由某人在PR中添加的,与您发现的情况非常相似。