如何根据环境(生产与开发)更改 Snap 应用程序的行为?

How can I change the behavior of a Snap application depending on the environment (Production vs. Development)?

Snap 中未捕获的运行时异常的默认行为是显示包含错误的白页。这对于开发模式来说很棒,但对于生产模式来说真的很糟糕。

我的应用程序设置为捕获异常并记录错误,以便在发生不良事件时显示对用户更有吸引力的内容。我怎样才能更改它以便仅在我处于生产模式时发生这种情况?

app :: SnapletInit App App
app = makeSnaplet "app" "An snaplet example application." Nothing $ do
    h <- nestSnaplet "" heist $ heistInit "templates"
    s <- nestSnaplet "sess" sess $
                 initCookieSessionManager "site_key.txt" "sess" (Just 86400)

    d <- nestSnaplet "db" db pgsInit

    addRoutes routes

    wrapSite (<|> notFound)
    -- TODO: figure out how make this only catch errors when in production mode
    wrapSite internalServerError

    initFlashNotice h sess
    addConfig h $ mempty & scInterpretedSplices .~ userSessionSplices sess
    return $ App h s d

internalServerError :: AppHandler () -> AppHandler ()
internalServerError h =
    catch h (\ (e :: SomeException) -> do
        logError $ B.pack $ show e
        modifyResponse (setResponseCode 500)
        render "errors/500")

在为开发模式编译时,有一个 DEVELOPMENT 标志传递给预处理器。

#ifndef DEVELOPMENT
wrapSite internalServerError
#endif

这很丑陋,我真的希望有更好的东西,因为它只能通过重新编译才能工作。

Snap 提供 getEnvironment function for this purpose. This function gets the environment passed to runSnaplet。环境默认为 "devel",但可以在 运行 时使用 -e 命令行选项进行更改。如果您 运行 您的应用程序是这样的:

dist/build/myapp/myapp -e prod

然后 getEnvironment 将 return "prod"。你可以这样使用它:

notFound = do
  e <- getEnvironment
  case e of
    "devel" -> develErrorPage
    _       -> productionErrorPage