diff --git a/README.md b/README.md
index c6785aea..bfe4e4ce 100644
--- a/README.md
+++ b/README.md
@@ -19,15 +19,44 @@ Scotty is the cheap and cheerful way to write RESTful, declarative web applicati
* Conforms to the [web application interface (WAI)](https://github.com/yesodweb/wai/).
* Uses the very fast Warp webserver by default.
-See examples/basic.hs to see Scotty in action. (basic.hs needs the wai-extra package)
+As for the name: Sinatra + Warp = Scotty.
+
+## Examples
+
+Run /basic.hs to see Scotty in action:
```bash
-> runghc examples/basic.hs
-Setting phasers to stun... (port 3000) (ctrl-c to quit)
-(visit localhost:3000/somepath)
+runghc examples/basic.hs
```
+`Setting phasers to stun... (port 3000) (ctrl-c to quit)`
-As for the name: Sinatra + Warp = Scotty.
+Or equivalently with [`stack`](https://docs.haskellstack.org/en/stable/):
+
+```bash
+stack exec -- scotty-basic
+```
+
+Once the server is running you can interact with it with curl or a browser:
+
+```bash
+curl localhost:3000
+```
+`foobar`
+
+```bash
+curl localhost:3000/foo_query?p=42
+```
+`
42
`
+
+
+Additionally, the `examples` directory shows a number of concrete use cases, e.g.
+
+* [exception handling](./examples/exceptions.hs)
+* [global state](./examples/globalstate.hs)
+* [configuration](./examples/reader.hs)
+* [cookies](./examples/cookies.hs)
+* [file upload](./examples/upload.hs)
+* and more
## More Information
diff --git a/Web/Scotty.hs b/Web/Scotty.hs
index 5317f085..deced828 100644
--- a/Web/Scotty.hs
+++ b/Web/Scotty.hs
@@ -5,9 +5,16 @@
-- Scotty is set up by default for development mode. For production servers,
-- you will likely want to modify 'Trans.settings' and the 'defaultHandler'. See
-- the comments on each of these functions for more information.
+--
+-- Please refer to the @examples@ directory and the @spec@ test suite for concrete use cases, e.g. constructing responses, exception handling and useful implementation details.
module Web.Scotty
- ( -- * scotty-to-WAI
- scotty, scottyApp, scottyOpts, scottySocket, Options(..), defaultOptions
+ ( -- * Running 'scotty' servers
+ scotty
+ , scottyOpts
+ , scottySocket
+ , Options(..), defaultOptions
+ -- ** scotty-to-WAI
+ , scottyApp
-- * Defining Middleware and Routes
--
-- | 'Middleware' and routes are run in the order in which they
@@ -40,7 +47,7 @@ module Web.Scotty
-- * Parsing Parameters
, Param, Trans.Parsable(..), Trans.readEither
-- * Types
- , ScottyM, ActionM, RoutePattern, File, Content(..), Kilobytes, Handler(..)
+ , ScottyM, ActionM, RoutePattern, File, Content(..), Kilobytes, ErrorHandler, Handler(..)
, ScottyState, defaultScottyState
) where
diff --git a/Web/Scotty/Trans.hs b/Web/Scotty/Trans.hs
index 117accad..d78eda3b 100644
--- a/Web/Scotty/Trans.hs
+++ b/Web/Scotty/Trans.hs
@@ -4,15 +4,22 @@
-- OverloadedStrings language pragma.
--
-- The functions in this module allow an arbitrary monad to be embedded
--- in Scotty's monad transformer stack in order that Scotty be combined
--- with other DSLs.
+-- in Scotty's monad transformer stack, e.g. for complex endpoint configuration,
+-- interacting with databases etc.
--
-- Scotty is set up by default for development mode. For production servers,
-- you will likely want to modify 'settings' and the 'defaultHandler'. See
-- the comments on each of these functions for more information.
+--
+-- Please refer to the @examples@ directory and the @spec@ test suite for concrete use cases, e.g. constructing responses, exception handling and useful implementation details.
module Web.Scotty.Trans
- ( -- * scotty-to-WAI
- scottyT, scottyAppT, scottyOptsT, scottySocketT, Options(..), defaultOptions
+ ( -- * Running 'scotty' servers
+ scottyT
+ , scottyOptsT
+ , scottySocketT
+ , Options(..), defaultOptions
+ -- ** scotty-to-WAI
+ , scottyAppT
-- * Defining Middleware and Routes
--
-- | 'Middleware' and routes are run in the order in which they
diff --git a/examples/basic.hs b/examples/basic.hs
index c489bdfd..3c2c33ce 100644
--- a/examples/basic.hs
+++ b/examples/basic.hs
@@ -35,10 +35,20 @@ main = scotty 3000 $ do
get "/" $ text "foobar"
get "/" $ text "barfoo"
- -- Using a parameter in the query string. Since it has
- -- not been given, a 500 page is generated.
- get "/foo" $ do
- v <- pathParam "fooparam"
+ -- Looking for a parameter in the path. Since the path pattern does not
+ -- contain the parameter name 'p', the server responds with 500 Server Error.
+ get "/foo_fail" $ do
+ v <- pathParam "p"
+ html $ mconcat ["", v, "
"]
+
+ -- Looking for a parameter 'p' in the path.
+ get "/foo_path/:p" $ do
+ v <- pathParam "p"
+ html $ mconcat ["", v, "
"]
+
+ -- Looking for a parameter 'p' in the query string.
+ get "/foo_query" $ do
+ v <- queryParam "p"
html $ mconcat ["", v, "
"]
-- An uncaught error becomes a 500 page.
diff --git a/examples/exceptions.hs b/examples/exceptions.hs
index 4faf1a69..6bf050c2 100644
--- a/examples/exceptions.hs
+++ b/examples/exceptions.hs
@@ -5,6 +5,7 @@ module Main (main) where
import Control.Exception (Exception(..))
import Control.Monad.IO.Class
+import Control.Monad.IO.Unlift (MonadUnliftIO(..))
import Data.String (fromString)
import Data.Typeable
@@ -34,8 +35,12 @@ handleEx = Handler $ \case
html $ fromString $ "" ++ s ++ "
"
main :: IO ()
-main = scottyT 3000 id $ do -- note, we aren't using any additional transformer layers
- -- so we can just use 'id' for the runner.
+main = do
+ scottyT 3000 id server -- note: we use 'id' since we don't have to run any effects at each action
+
+-- Any custom monad stack will need to implement 'MonadUnliftIO'
+server :: MonadUnliftIO m => ScottyT m ()
+server = do
middleware logStdoutDev
defaultHandler handleEx -- define what to do with uncaught exceptions
diff --git a/examples/scotty-examples.cabal b/examples/scotty-examples.cabal
index 47b44214..3a4fe64f 100644
--- a/examples/scotty-examples.cabal
+++ b/examples/scotty-examples.cabal
@@ -66,6 +66,7 @@ executable scotty-exceptions
random,
scotty,
transformers,
+ unliftio-core,
wai-extra
GHC-options: -Wall -threaded