diff --git a/Web/Scotty.hs b/Web/Scotty.hs
--- a/Web/Scotty.hs
+++ b/Web/Scotty.hs
@@ -171,12 +171,12 @@
 setHeader = Trans.setHeader
 
 -- | Set the body of the response to the given 'Text' value. Also sets \"Content-Type\"
--- header to \"text/plain; charset=utf-8\".
+-- header to \"text/plain; charset=utf-8\" if it has not already been set.
 text :: Text -> ActionM ()
 text = Trans.text
 
 -- | Set the body of the response to the given 'Text' value. Also sets \"Content-Type\"
--- header to \"text/html; charset=utf-8\".
+-- header to \"text/html; charset=utf-8\" if it has not already been set.
 html :: Text -> ActionM ()
 html = Trans.html
 
@@ -186,7 +186,7 @@
 file = Trans.file
 
 -- | Set the body of the response to the JSON encoding of the given value. Also sets \"Content-Type\"
--- header to \"application/json; charset=utf-8\".
+-- header to \"application/json; charset=utf-8\" if it has not already been set.
 json :: ToJSON a => a -> ActionM ()
 json = Trans.json
 
diff --git a/Web/Scotty/Action.hs b/Web/Scotty/Action.hs
--- a/Web/Scotty/Action.hs
+++ b/Web/Scotty/Action.hs
@@ -1,4 +1,6 @@
-{-# LANGUAGE CPP, OverloadedStrings, RankNTypes #-}
+{-# LANGUAGE CPP               #-}
+{-# LANGUAGE OverloadedStrings #-}
+{-# LANGUAGE RankNTypes        #-}
 module Web.Scotty.Action
     ( addHeader
     , body
@@ -28,7 +30,7 @@
     , runAction
     ) where
 
-import           Blaze.ByteString.Builder (fromLazyByteString)
+import           Blaze.ByteString.Builder   (fromLazyByteString)
 
 #if MIN_VERSION_mtl(2,2,1)
 import           Control.Monad.Except
@@ -36,17 +38,17 @@
 import           Control.Monad.Error
 #endif
 import           Control.Monad.Reader
-import qualified Control.Monad.State as MS
+import qualified Control.Monad.State        as MS
 
-import qualified Data.Aeson as A
-import qualified Data.ByteString.Char8 as B
+import qualified Data.Aeson                 as A
+import qualified Data.ByteString.Char8      as B
 import qualified Data.ByteString.Lazy.Char8 as BL
-import qualified Data.CaseInsensitive as CI
-import           Data.Default (def)
-import           Data.Monoid (mconcat)
-import qualified Data.Text as ST
-import qualified Data.Text.Lazy as T
-import           Data.Text.Lazy.Encoding (encodeUtf8)
+import qualified Data.CaseInsensitive       as CI
+import           Data.Default               (def)
+import           Data.Monoid                (mconcat)
+import qualified Data.Text                  as ST
+import qualified Data.Text.Lazy             as T
+import           Data.Text.Lazy.Encoding    (encodeUtf8)
 
 import           Network.HTTP.Types
 import           Network.Wai
@@ -151,7 +153,7 @@
 jsonData :: (A.FromJSON a, ScottyError e, Monad m) => ActionT e m a
 jsonData = do
     b <- body
-    maybe (raise $ stringError $ "jsonData - no parse: " ++ BL.unpack b) return $ A.decode b
+    either (\e -> raise $ stringError $ "jsonData - no parse: " ++ e ++ ". Data was:" ++ BL.unpack b) return $ A.eitherDecode b
 
 -- | Get a parameter. First looks in captures, then form data, then query parameters.
 --
@@ -186,6 +188,7 @@
 instance Parsable T.Text where parseParam = Right
 instance Parsable ST.Text where parseParam = Right . T.toStrict
 instance Parsable B.ByteString where parseParam = Right . lazyTextToStrictByteString
+instance Parsable BL.ByteString where parseParam = Right . encodeUtf8
 -- | Overrides default 'parseParamList' to parse String.
 instance Parsable Char where
     parseParam t = case T.unpack t of
@@ -215,7 +218,7 @@
 -- | Useful for creating 'Parsable' instances for things that already implement 'Read'. Ex:
 --
 -- > instance Parsable Int where parseParam = readEither
-readEither :: (Read a) => T.Text -> Either T.Text a
+readEither :: Read a => T.Text -> Either T.Text a
 readEither t = case [ x | (x,"") <- reads (T.unpack t) ] of
                 [x] -> Right x
                 []  -> Left "readEither: no parse"
@@ -225,27 +228,37 @@
 status :: (ScottyError e, Monad m) => Status -> ActionT e m ()
 status = ActionT . MS.modify . setStatus
 
+-- Not exported, but useful in the functions below.
+changeHeader :: (ScottyError e, Monad m)
+             => (CI.CI B.ByteString -> B.ByteString -> [(HeaderName, B.ByteString)] -> [(HeaderName, B.ByteString)])
+             -> T.Text -> T.Text -> ActionT e m ()
+changeHeader f k = ActionT
+                 . MS.modify
+                 . setHeaderWith
+                 . f (CI.mk $ lazyTextToStrictByteString k)
+                 . lazyTextToStrictByteString
+
 -- | Add to the response headers. Header names are case-insensitive.
 addHeader :: (ScottyError e, Monad m) => T.Text -> T.Text -> ActionT e m ()
-addHeader k v = ActionT . MS.modify $ setHeaderWith $ add (CI.mk $ lazyTextToStrictByteString k) (lazyTextToStrictByteString v)
+addHeader = changeHeader add
 
 -- | Set one of the response headers. Will override any previously set value for that header.
 -- Header names are case-insensitive.
 setHeader :: (ScottyError e, Monad m) => T.Text -> T.Text -> ActionT e m ()
-setHeader k v = ActionT . MS.modify $ setHeaderWith $ replace (CI.mk $ lazyTextToStrictByteString k) (lazyTextToStrictByteString v)
+setHeader = changeHeader replace
 
 -- | Set the body of the response to the given 'T.Text' value. Also sets \"Content-Type\"
--- header to \"text/plain; charset=utf-8\".
+-- header to \"text/plain; charset=utf-8\" if it has not already been set.
 text :: (ScottyError e, Monad m) => T.Text -> ActionT e m ()
 text t = do
-    setHeader "Content-Type" "text/plain; charset=utf-8"
+    changeHeader addIfNotPresent "Content-Type" "text/plain; charset=utf-8"
     raw $ encodeUtf8 t
 
 -- | Set the body of the response to the given 'T.Text' value. Also sets \"Content-Type\"
--- header to \"text/html; charset=utf-8\".
+-- header to \"text/html; charset=utf-8\" if it has not already been set.
 html :: (ScottyError e, Monad m) => T.Text -> ActionT e m ()
 html t = do
-    setHeader "Content-Type" "text/html; charset=utf-8"
+    changeHeader addIfNotPresent "Content-Type" "text/html; charset=utf-8"
     raw $ encodeUtf8 t
 
 -- | Send a file as the response. Doesn't set the \"Content-Type\" header, so you probably
@@ -254,10 +267,10 @@
 file = ActionT . MS.modify . setContent . ContentFile
 
 -- | Set the body of the response to the JSON encoding of the given value. Also sets \"Content-Type\"
--- header to \"application/json; charset=utf-8\".
+-- header to \"application/json; charset=utf-8\" if it has not already been set.
 json :: (A.ToJSON a, ScottyError e, Monad m) => a -> ActionT e m ()
 json v = do
-    setHeader "Content-Type" "application/json; charset=utf-8"
+    changeHeader addIfNotPresent "Content-Type" "application/json; charset=utf-8"
     raw $ A.encode v
 
 -- | Set the body of the response to a Source. Doesn't set the
diff --git a/Web/Scotty/Internal/Types.hs b/Web/Scotty/Internal/Types.hs
--- a/Web/Scotty/Internal/Types.hs
+++ b/Web/Scotty/Internal/Types.hs
@@ -150,21 +150,21 @@
 
 instance ScottyError e => MonadTransControl (ActionT e) where
 #if MIN_VERSION_mtl(2,2,1)
-     newtype StT (ActionT e) a = StAction {unStAction :: StT (StateT ScottyResponse) (StT (ReaderT ActionEnv) (StT (ExceptT (ActionError e)) a))}
+     type StT (ActionT e) a = StT (StateT ScottyResponse) (StT (ReaderT ActionEnv) (StT (ExceptT (ActionError e)) a))
 #else
-     newtype StT (ActionT e) a = StAction {unStAction :: StT (StateT ScottyResponse) (StT (ReaderT ActionEnv) (StT (ErrorT (ActionError e)) a))}
+     type StT (ActionT e) a = StT (StateT ScottyResponse) (StT (ReaderT ActionEnv) (StT (ErrorT (ActionError e)) a))
 #endif
      liftWith = \f ->
         ActionT $  liftWith $ \run  ->
                    liftWith $ \run' ->
                    liftWith $ \run'' ->
-                   f $ liftM StAction . run'' . run' . run . runAM
-     restoreT = ActionT . restoreT . restoreT . restoreT . liftM unStAction
+                   f $ run'' . run' . run . runAM
+     restoreT = ActionT . restoreT . restoreT . restoreT
 
 instance (ScottyError e, MonadBaseControl b m) => MonadBaseControl b (ActionT e m) where
-    newtype StM (ActionT e m) a = STMAction {unStMActionT :: ComposeSt (ActionT e) m a}
-    liftBaseWith = defaultLiftBaseWith STMAction
-    restoreM     = defaultRestoreM   unStMActionT
+    type StM (ActionT e m) a = ComposeSt (ActionT e) m a
+    liftBaseWith = defaultLiftBaseWith
+    restoreM     = defaultRestoreM
 
 ------------------ Scotty Routes --------------------
 data RoutePattern = Capture   Text
diff --git a/Web/Scotty/Route.hs b/Web/Scotty/Route.hs
--- a/Web/Scotty/Route.hs
+++ b/Web/Scotty/Route.hs
@@ -1,4 +1,4 @@
-{-# LANGUAGE CPP, FlexibleContexts, FlexibleInstances, LambdaCase,
+{-# LANGUAGE CPP, FlexibleContexts, FlexibleInstances,
              OverloadedStrings, RankNTypes, ScopedTypeVariables #-}
 module Web.Scotty.Route
     ( get, post, put, delete, patch, addroute, matchAny, notFound,
@@ -124,9 +124,9 @@
         Just rbt -> do
             mvar <- liftIO $ newMVar bl -- MVar is a bit of a hack so we don't have to inline
                                         -- large portions of Network.Wai.Parse
-            let provider = takeMVar mvar >>= \case
-                                                []     -> putMVar mvar [] >> return B.empty
-                                                (b:bs) -> putMVar mvar bs >> return b
+            let provider = modifyMVar mvar $ \bsold -> case bsold of
+                                                []     -> return ([], B.empty)
+                                                (b:bs) -> return (bs, b)
             liftIO $ Parse.sinkRequestBody s rbt provider
 
 mkEnv :: forall m. MonadIO m => Request -> [Param] -> m ActionEnv
diff --git a/Web/Scotty/Trans.hs b/Web/Scotty/Trans.hs
--- a/Web/Scotty/Trans.hs
+++ b/Web/Scotty/Trans.hs
@@ -89,7 +89,7 @@
            -> n Application
 scottyAppT runM runActionToIO defs = do
     s <- runM $ execStateT (runS defs) def
-    let rapp = \ req callback -> runActionToIO (foldl (flip ($)) notFoundApp (routes s) req) >>= callback
+    let rapp req callback = runActionToIO (foldl (flip ($)) notFoundApp (routes s) req) >>= callback
     return $ foldl (flip ($)) rapp (middlewares s)
 
 notFoundApp :: Monad m => Scotty.Application m
diff --git a/Web/Scotty/Util.hs b/Web/Scotty/Util.hs
--- a/Web/Scotty/Util.hs
+++ b/Web/Scotty/Util.hs
@@ -7,6 +7,7 @@
     , mkResponse
     , replace
     , add
+    , addIfNotPresent
     ) where
 
 import Network.Wai
@@ -46,8 +47,15 @@
           h = srHeaders sr
 
 -- Note: we assume headers are not sensitive to order here (RFC 2616 specifies they are not)
-replace :: (Eq a) => a -> b -> [(a,b)] -> [(a,b)]
-replace k v m = add k v $ filter ((/= k) . fst) m
+replace :: Eq a => a -> b -> [(a,b)] -> [(a,b)]
+replace k v = add k v . filter ((/= k) . fst)
 
-add :: (Eq a) => a -> b -> [(a,b)] -> [(a,b)]
+add :: Eq a => a -> b -> [(a,b)] -> [(a,b)]
 add k v m = (k,v):m
+
+addIfNotPresent :: Eq a => a -> b -> [(a,b)] -> [(a,b)]
+addIfNotPresent k v = go
+    where go []         = [(k,v)]
+          go l@((x,y):r)
+            | x == k    = l
+            | otherwise = (x,y) : go r
diff --git a/changelog.md b/changelog.md
--- a/changelog.md
+++ b/changelog.md
@@ -1,3 +1,13 @@
+## 0.9.1
+
+* `Parsable` instance for lazy bytestrings
+
+* `jsonData` now returns decoding error message
+
+* text/html/json only set Content-Type header when not already set
+
+* Bump `monad-control` to 1.0.0.0
+
 ## 0.9.0
 
 * Add `charset=utf-8` to `Content-Type` for `text`, `html` and `json`
diff --git a/examples/basic.hs b/examples/basic.hs
--- a/examples/basic.hs
+++ b/examples/basic.hs
@@ -63,6 +63,7 @@
     -- Files are streamed directly to the client.
     get "/404" $ file "404.html"
 
+    -- You can stop execution of this action and keep pattern matching routes.
     get "/random" $ do
         next
         redirect "http://www.we-never-go-here.com"
diff --git a/scotty.cabal b/scotty.cabal
--- a/scotty.cabal
+++ b/scotty.cabal
@@ -1,5 +1,5 @@
 Name:                scotty
-Version:             0.9.0
+Version:             0.9.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
@@ -76,9 +76,9 @@
                        data-default     >= 0.5.3    && < 0.6,
                        http-types       >= 0.8.2    && < 0.9,
                        mtl              >= 2.1.2    && < 2.3,
-                       monad-control    >= 0.3.2.3  && < 0.4,
+                       monad-control    >= 1.0.0.0  && < 1.1,
                        regex-compat     >= 0.95.1   && < 0.96,
-                       text             >= 0.11.3.1 && < 1.2,
+                       text             >= 0.11.3.1 && < 1.3,
                        transformers     >= 0.3.0.0  && < 0.5,
                        transformers-base >= 0.4.1   && < 0.5,
                        wai              >= 3.0.0    && < 3.1,
@@ -98,8 +98,8 @@
                        http-types,
                        lifted-base,
                        wai,
-                       hspec2,
-                       hspec-wai >= 0.3.0,
+                       hspec == 2.*,
+                       hspec-wai >= 0.5,
                        scotty
   GHC-options:         -Wall -fno-warn-orphans
 
