【问题标题】:Catch program errors in Happstack request handler在 Happstack 请求处理程序中捕获程序错误
【发布时间】:2018-04-27 13:48:04
【问题描述】:

我是 Haskell 的菜鸟,所以我不完全确定这是 Happstack 问题还是一般 Haskell 问题。

这是我遇到的困难的一个例子。这段代码“理论上”渲染了一些内容,但实际上抛出了一个错误:

throwsError :: String
throwsError = fromJust Nothing

-- no error page
main :: IO ()
main = do
  simpleHTTP nullConf $ do
    decodeBody (defaultBodyPolicy "/tmp/" 4096 4096 4096)
    ok $ toResponse throwsError

此错误不会使整个程序崩溃。幸运的是,Happstack 可以捕获在处理请求时抛出的任何错误,就像 Web 服务器应该做的那样。但是,不幸的是,它不会向用户显示任何类型的错误页面。它以状态码 200 和空内容进行响应。

现在,如果我只是先输出错误字符串:

-- yes error page
main :: IO ()
main = do
  simpleHTTP nullConf $ do
    decodeBody (defaultBodyPolicy "/tmp/" 4096 4096 4096)
    lift $ putStrLn throwsError -- added this line
    ok $ toResponse throwsError

Happstack 返回状态 500 并显示错误页面。为什么 Happstack 会这样?

ServerPart monad 实现了MonadThrow,所以我尝试导入Control.Monad.Catch (handle) 并编写此代码,但它没有达到我的预期;它再次返回 200 没有内容:

showErrorPage :: SomeException -> ServerPart Response
showErrorPage _ = internalServerError $ toResponse "Error"

-- also no error page
main :: IO ()
main = do
  simpleHTTP nullConf $ handle showErrorPage $ do
    decodeBody (defaultBodyPolicy "/tmp/" 4096 4096 4096)
    ok $ toResponse throwsError

如果不清楚,我想处理所有抛出的错误,以便记录它们并显示自定义错误页面。 (当然,记录和显示错误页面时抛出的错误除外)。指导将不胜感激。

【问题讨论】:

  • 我对Happstack了解不多,但我猜这和return undefined(不是bottom,而是计算结果是bottom)和putStrLn undefined之间的区别是一样的(这是底部)。

标签: haskell exception-handling happstack


【解决方案1】:

顺便说一句,我找到了答案。基本上它与惰性评估有关 - Response 对象仅在 Happstack 内部开始将数据流式传输到响应正文之后才评估为 WHNF,此时将状态代码从 200 更改为 500 为时已晚。

如果响应是视频流,则这是正确的行为,因为在这种情况下,在发送 HTTP 响应之前严格评估响应以确保它不包含任何 undefined 值会很麻烦。但是,对于 实用 的已知小响应,要深入、严格地评估以消除任何底部值的可能性,这显然是不方便的。此外,HTTP 客户端(主要是浏览器)隐含地假设 200 响应代码意味着请求成功 - 只有在特定情况下,例如流媒体视频,200 响应才以任何方式“不可信”并且代码消耗HTTP 响应对其进行了更深入的研究,以确保在处理并将其显示给最终用户之前它的格式和格式正确 - 实际上正如我在问题中看到的那样,因为浏览器显示一个空白页面并且网络选项卡显示 @987654324 @ 没有内容,即使有很多内部服务器错误。

Here 是我对 Happstack 的拉取请求,它只是将一些类型类添加到 Response 对象,以便在将其返回到 ServerPart monad 之前对其进行深入、严格的评估。那个特定的 PR 有一段麻烦的历史(它曾经做过一些更大范围的事情),所以我可能会关闭它并打开一个新的。如果是这样,则应将其标记为已关闭并具有指向新的链接。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-26
    • 2019-10-27
    • 2019-05-03
    • 1970-01-01
    • 1970-01-01
    • 2020-11-03
    • 1970-01-01
    相关资源
    最近更新 更多