cimmanon
cimmanon

Reputation: 68339

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

The default behavior for an uncaught runtime exception in Snap is to display a white page containing the error. This is great for development mode, but really terrible for production.

I have my application setup to catch the exception and log the error so that displays something more attractive to the user when something bad happens. How can I change it so that this only happens when I am in production mode?

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")

Upvotes: -1

Views: 131

Answers (2)

mightybyte
mightybyte

Reputation: 7282

Snap provides the getEnvironment function for this purpose. This function gets the environment passed to runSnaplet. The environment defaults to "devel" but can be changed at runtime with the -e command line option. If you run your application like this:

dist/build/myapp/myapp -e prod

Then getEnvironment will return "prod". You can use that like this:

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

Upvotes: 0

Alain O&#39;Dea
Alain O&#39;Dea

Reputation: 21716

There is a DEVELOPMENT flag passed to the preprocessor when compiling for development mode.

#ifndef DEVELOPMENT
wrapSite internalServerError
#endif

This is ugly and I was really hoping there was something better since it only works by recompiling.

Upvotes: 1

Related Questions