如何从 Handler 中抛出异常
How to throw exceptions from Handler
我正在构建一个 RESTful 端点,如果存在无效数据,它应该会抛出错误。这是一个简化的(有点傻)版本:
getEventsR :: Handler Value
getEventsR = do
mpage <- lookupGetParam "page"
let filters = case hasPage mpage of
Right val -> val
Left val -> error $ T.unpack val -- Throw an error
-- The rest...
hasPage :: Maybe Text -> Either Text Text
hasPage =
Left "This should error out"
- 这是正确的方法吗 - 一个函数应该 return 一个
Either
稍后将被扩展为一个错误?
- 我可能不应该使用
error
,对吧?取而代之的是什么?
附带说明一下,如果我抛出的错误也能以 JSON 格式发送,我会很高兴。
更新:
我使用术语 "throw exception" 的原因是因为我的代码看起来像这样(简化):
let selectOpt = case addPager [] of
Right val -> val
Left val -> error $ T.unpack val
let filters = case addFilter [] of
Right val -> val
Left val -> error $ T.unpack val
events <- runDB $ selectList filters selectOpt :: Handler [Entity Event]
因此,如果它在 selectOpt
上出错,我希望它短路,而不是继续处理程序的其余部分。
您可以使用sendResponseStatus
直接指定响应:
getEventsR = do
mpage <- lookupGetParam "page"
case hasPage mpage of
Left message -> sendResponseStatus status400 message
Right val -> ...continue processing with val...
sendResponseStatus
的第二个参数可以是任何具有 ToTypedContent
实例的类型。这包括 Text
、Value
和其他常见类型。有关默认定义此实例的类型,请参阅 this page。
更新
回应您的意见...
get404
定义为:
get404 key = do
mres <- get key
case mres of
Nothing -> notFound'
Just res -> return res
notFound' :: MonadIO m => m a
notFound' = liftIO $ throwIO $ HCError NotFound
HCError
是 HandlerContents
类型的构造函数:
http://hackage.haskell.org/package/yesod-core-1.4.0/docs/Yesod-Core-Types.html#t:HandlerContents
data HandlerContents:
HCContent Status !TypedContent
HCError ErrorResponse
HCSendFile ContentType FilePath (Maybe FilePart)
HCRedirect Status Text
HCCreated Text
HCWai Response
HCWaiApp Application
ErrorResponse
具有以下构造函数:
data ErrorResponse:
NotFound
InternalError Text
InvalidArgs [Text]
NotAuthenticated
PermissionDenied Text
BadMethod Method
所以你可以throwIO
限制错误的数量,错误信息限制在Text
。
我正在构建一个 RESTful 端点,如果存在无效数据,它应该会抛出错误。这是一个简化的(有点傻)版本:
getEventsR :: Handler Value
getEventsR = do
mpage <- lookupGetParam "page"
let filters = case hasPage mpage of
Right val -> val
Left val -> error $ T.unpack val -- Throw an error
-- The rest...
hasPage :: Maybe Text -> Either Text Text
hasPage =
Left "This should error out"
- 这是正确的方法吗 - 一个函数应该 return 一个
Either
稍后将被扩展为一个错误? - 我可能不应该使用
error
,对吧?取而代之的是什么?
附带说明一下,如果我抛出的错误也能以 JSON 格式发送,我会很高兴。
更新:
我使用术语 "throw exception" 的原因是因为我的代码看起来像这样(简化):
let selectOpt = case addPager [] of
Right val -> val
Left val -> error $ T.unpack val
let filters = case addFilter [] of
Right val -> val
Left val -> error $ T.unpack val
events <- runDB $ selectList filters selectOpt :: Handler [Entity Event]
因此,如果它在 selectOpt
上出错,我希望它短路,而不是继续处理程序的其余部分。
您可以使用sendResponseStatus
直接指定响应:
getEventsR = do
mpage <- lookupGetParam "page"
case hasPage mpage of
Left message -> sendResponseStatus status400 message
Right val -> ...continue processing with val...
sendResponseStatus
的第二个参数可以是任何具有 ToTypedContent
实例的类型。这包括 Text
、Value
和其他常见类型。有关默认定义此实例的类型,请参阅 this page。
更新
回应您的意见...
get404
定义为:
get404 key = do
mres <- get key
case mres of
Nothing -> notFound'
Just res -> return res
notFound' :: MonadIO m => m a
notFound' = liftIO $ throwIO $ HCError NotFound
HCError
是 HandlerContents
类型的构造函数:
http://hackage.haskell.org/package/yesod-core-1.4.0/docs/Yesod-Core-Types.html#t:HandlerContents
data HandlerContents:
HCContent Status !TypedContent
HCError ErrorResponse
HCSendFile ContentType FilePath (Maybe FilePart)
HCRedirect Status Text
HCCreated Text
HCWai Response
HCWaiApp Application
ErrorResponse
具有以下构造函数:
data ErrorResponse:
NotFound
InternalError Text
InvalidArgs [Text]
NotAuthenticated
PermissionDenied Text
BadMethod Method
所以你可以throwIO
限制错误的数量,错误信息限制在Text
。