在Happstack请求处理程序中捕获程序错误



我有点不了解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会这样?

ServerPartmonad实现了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

如果不清楚,我想处理所有抛出的错误,这样我就可以记录它们并显示自定义错误页面。(当然,除了在记录和显示错误页面时抛出的错误)。请提供指导。

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

如果响应是视频流,这是正确的行为,因为在发送HTTP响应之前,严格评估响应以确保其不包含任何undefined值在这种情况下会很困难。然而,对于具有实用性的已知小响应来说,深入、严格地评估以消除任何底部值的可能性显然是不方便的。此外HTTP客户端(主要是浏览器)隐含地认为200响应代码意味着请求成功,只有在流媒体视频等特定情况下,200响应才是"不可信的",而使用HTTP响应的代码会更深入地查看它,以确保它在处理和显示给最终用户之前格式良好,格式正确在我的问题中看到,浏览器显示一个空页面,网络选项卡显示200,没有内容,尽管存在很大的内部服务器错误。

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

相关内容

  • 没有找到相关文章

最新更新