【问题标题】:How to throw exceptions from Handler如何从 Handler 抛出异常
【发布时间】:2016-05-31 03:18:27
【问题描述】:

我正在构建一个 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"
  1. 这是正确的方法吗?函数应该返回一个Either,稍后会扩展为一个错误?
  2. 我可能不应该使用error,对吧?取而代之的是什么?

附带说明,如果我抛出的错误也以 JSON 格式发送,我会很高兴。

更新:

我使用术语“抛出异常”的原因是因为我的代码看起来像这样(简化):

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 上出错,我希望它短路,而不是继续处理程序的其余部分。

【问题讨论】:

  • 你想“抛出异常”做什么?服务器崩溃?返回一个 HTTP 响应(比如 500 或 404?)
  • 返回一个 HTTP 响应(例如 400)以及一条消息。 (例如{ error: "This should error out" }

标签: haskell yesod


【解决方案1】:

您可以使用sendResponseStatus 直接指定响应:

getEventsR = do
  mpage   <- lookupGetParam "page"
  case hasPage mpage of
    Left message -> sendResponseStatus status400 message
    Right val    -> ...continue processing with val...

sendResponseStatus 的第二个参数可以是具有ToTypedContent 实例的任何类型。这包括TextValue 和其他常见类型。有关默认定义此实例的类型,请参阅 this page

更新

响应您的 cmets...

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

HCErrorHandlerContents 类型的构造函数:

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

【讨论】:

  • 谢谢。我更新了问题,以更好地反映我为什么使用“抛出异常”一词
  • 例如,我相信event &lt;- runDB $ get404 eid - 知道如何短路,并发送404 - 但我自己不明白如何做类似的事情:)
猜你喜欢
  • 2016-12-25
  • 2013-05-24
  • 2012-08-23
  • 2014-04-03
  • 2017-08-13
  • 2011-07-17
  • 2017-11-08
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多