Skip to content

Commit

Permalink
bugfix release v 0.20.1 (#326)
Browse files Browse the repository at this point in the history
* v 0.20.1

* add MonadFail tests

* add MonadError StatusError (ActionT m) instance and raise lower bound on base

* upd changelog
---------

Co-authored-by: Marco Zocca <[email protected]>
  • Loading branch information
ocramz and Marco Zocca authored Oct 3, 2023
1 parent 1928910 commit bb50e65
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 5 deletions.
11 changes: 10 additions & 1 deletion Web/Scotty/Internal/Types.hs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
{-# LANGUAGE CPP #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DerivingStrategies #-}
{-# language DerivingVia #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE MultiParamTypeClasses #-}
Expand All @@ -20,6 +19,7 @@ import qualified Control.Exception as E
import Control.Monad (MonadPlus(..))
import Control.Monad.Base (MonadBase)
import Control.Monad.Catch (MonadCatch, MonadThrow)
import Control.Monad.Error.Class (MonadError(..))
import Control.Monad.IO.Class (MonadIO(..))
import UnliftIO (MonadUnliftIO(..))
import Control.Monad.Reader (MonadReader(..), ReaderT, asks)
Expand Down Expand Up @@ -207,6 +207,15 @@ defaultScottyResponse = SR status200 [] (ContentBuilder mempty)

newtype ActionT m a = ActionT { runAM :: ReaderT ActionEnv m a }
deriving newtype (Functor, Applicative, Monad, MonadIO, MonadReader ActionEnv, MonadTrans, MonadThrow, MonadCatch, MonadBase b, MonadBaseControl b, MonadTransControl, MonadUnliftIO)

-- | Models the invariant that only 'StatusError's can be thrown and caught.
instance (MonadUnliftIO m) => MonadError StatusError (ActionT m) where
throwError = E.throw
catchError = catch
-- | Modeled after the behaviour in scotty < 0.20, 'fail' throws a 'StatusError' with code 500 ("Server Error"), which can be caught with 'E.catch' or 'rescue'.
instance (MonadIO m) => MonadFail (ActionT m) where
fail = E.throw . StatusError status500 . pack
-- | 'empty' throws 'ActionError' 'AENext', whereas '(<|>)' catches any 'ActionError's or 'StatusError's in the first action and proceeds to the second one.
instance (MonadUnliftIO m) => Alternative (ActionT m) where
empty = E.throw AENext
a <|> b = do
Expand Down
11 changes: 9 additions & 2 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
## next [????.??.??]

## 0.20.1 [2023.10.03]

* remove dependencies on 'base-compat' and 'base-compat-batteries' (#318)
* re-add MonadFail (ActionT m) instance (#325)
* re-add MonadError (ActionT m) instance, but the error type is now specialized to 'StatusError' (#325)
* raise lower bound on base ( > 4.14 ) to reflect support for GHC >= 8.10 (#325).

## 0.20 [2023.10.02]
* Drop support for GHC < 8.10 and modernise the CI pipeline (#300).
Expand All @@ -14,8 +19,10 @@
Breaking:

* (#310) Introduce `unliftio` as a dependency, and base exception handling on `catch`.
** Clarify the exception handling mechanism of ActionT, ScottyT. `rescue` changes signature to use proper `Exception` types rather than strings.
** All ActionT methods (`text`, `html` etc.) have now a MonadIO constraint on the base monad rather than Monad because the response is constructed in a TVar inside ActionEnv. `rescue` has a MonadUnliftIO constraint. The Alternative instance of ActionT also is based on MonadUnliftIO because `<|>` is implemented in terms of `catch`. `ScottyT` and `ActionT` do not have an exception type parameter anymore.
* (#310) Clarify the exception handling mechanism of ActionT, ScottyT. `rescue` changes signature to use proper `Exception` types rather than strings. Remove `ScottyError` typeclass.
* (#310) All ActionT methods (`text`, `html` etc.) have now a MonadIO constraint on the base monad rather than Monad because the response is constructed in a TVar inside ActionEnv. `rescue` has a MonadUnliftIO constraint. The Alternative instance of ActionT also is based on MonadUnliftIO because `<|>` is implemented in terms of `catch`. `ScottyT` and `ActionT` do not have an exception type parameter anymore.
* (#310) MonadError e (ActionT m) instance removed
* (#310) MonadFail (ActionT m) instance is missing by mistake.

## 0.12.1 [2022.11.17]
* Fix CPP bug that prevented tests from building on Windows.
Expand Down
4 changes: 2 additions & 2 deletions scotty.cabal
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Name: scotty
Version: 0.20
Version: 0.20.1
Synopsis: Haskell web framework inspired by Ruby's Sinatra, using WAI and Warp
Homepage: https://github.com/scotty-web/scotty
Bug-reports: https://github.com/scotty-web/scotty/issues
Expand Down Expand Up @@ -69,7 +69,7 @@ Library
Web.Scotty.Util
default-language: Haskell2010
build-depends: aeson >= 0.6.2.1 && < 2.3,
base >= 4.6 && < 5,
base >= 4.14 && < 5,
blaze-builder >= 0.3.3.0 && < 0.5,
bytestring >= 0.10.0.2 && < 0.12,
case-insensitive >= 1.0.0.1 && < 1.3,
Expand Down
8 changes: 8 additions & 0 deletions test/Web/ScottySpec.hs
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,14 @@ spec = do
get "/dictionary?word2=y" `shouldRespondWith` "y"
get "/dictionary?word1=a&word2=b" `shouldRespondWith` "a"

context "MonadFail instance" $ do
withApp (Scotty.get "/" $ fail "boom!") $ do
it "returns 500 if not caught" $
get "/" `shouldRespondWith` 500
withApp (Scotty.get "/" $ (fail "boom!") `rescue` (\(_ :: StatusError) -> text "ok")) $
it "can catch the StatusError thrown by fail" $ do
get "/" `shouldRespondWith` 200 { matchBody = "ok"}

describe "redirect" $ do
withApp (
do
Expand Down

0 comments on commit bb50e65

Please sign in to comment.