scotty
Haskell web framework inspired by Ruby's Sinatra, using WAI and Warp
https://github.com/scotty-web/scotty
| Version on this page: | 0.11.2@rev:1 |
| LTS Haskell 24.17: | 0.22@rev:2 |
| Stackage Nightly 2025-10-26: | 0.22@rev:2 |
| Latest on Hackage: | 0.22@rev:2 |
scotty-0.11.2@sha256:e3fb51f3e908cced820815b2b74a4948195d0c81adae4530a69b9d8ef0998ec0,5024Module documentation for 0.11.2
- Web
- Web.Scotty
- Web.Scotty.Internal
- Web.Scotty.Trans
- Web.Scotty
Scotty 

A Haskell web framework inspired by Ruby’s Sinatra, using WAI and Warp.
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Data.Monoid (mconcat)
main = scotty 3000 $
get "/:word" $ do
beam <- param "word"
html $ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]
Scotty is the cheap and cheerful way to write RESTful, declarative web applications.
- A page is as simple as defining the verb, url pattern, and Text content.
- It is template-language agnostic. Anything that returns a Text value will do.
- Conforms to WAI Application interface.
- Uses very fast Warp webserver by default.
See examples/basic.hs to see Scotty in action. (basic.hs needs the wai-extra package)
> runghc examples/basic.hs
Setting phasers to stun... (port 3000) (ctrl-c to quit)
(visit localhost:3000/somepath)
As for the name: Sinatra + Warp = Scotty.
More Information
Tutorials and related projects can be found in the Scotty wiki:
https://github.com/scotty-web/scotty/wiki
Development & Support
Open an issue on GitHub or join #scotty on Freenode.
Copyright (c) 2012-2017 Andrew Farmer
Changes
0.11.2 [2018.07.02]
- Migrate from
NetworktoNetwork.Socketto avoid deprecation warnings.
0.11.1 [2018.04.07]
- Add
MonadThrowandMonadCatchinstances forActionT[abhinav] - Fix
matchAnyso that all methods are matched, not just standard ones [taphu]
0.11.0
- IO exceptions are no longer automatically turned into ScottyErrors by
liftIO. UseliftAndCatchIOto get that behavior. - New
finishfunction. - Text values are now leniently decoded from ByteStrings.
- Added
MonadFailinstance forScottyT - Lots of bound bumps on dependencies.
0.10.2
- Removed debug statement from routes
0.10.1
Parsableinstances forWord,Word8,Word16,Word32,Word64[adamflott]Parsableinstances forInt8,Int16,Int32,Int64, andNatural- Removed redundant
Monadconstraint onmiddleware
0.10.0
-
The monad parameters to
ScottyThave been decoupled, causing the type of theScottyTconstructor to change. As a result,ScottyTis no longer aMonadTransinstance, and the type signatures ofscottyT,scottyAppT, andscottyOptsThave been simplified. [ehamberg] -
socketDescriptionno longer uses the deprecatedPortNumconstructor. Instead, it uses theShowinstance forPortNumber. This changes the bytes from host to network order, so the output ofsocketDescriptioncould change. [ehamberg] -
Alternative,MonadPlusinstances forActionT -
scottynow depends ontransformers-compat. As a result,ActionTnow usesExceptT, regardless of which version oftransformersis used. As a result, several functions inWeb.Scotty.Transno longer require aScottyErrorconstraint, sinceExceptTdoes not require anErrorconstraint (unlikeErrorT). -
Added support for OPTIONS routes via the
optionsfunction [alvare] -
Add
scottySocketandscottySocketT, exposing Warp Unix socket support [hakujin] -
Parsableinstance for lazyByteString[tattsun] -
Added streaming uploads via the
bodyReaderfunction, which retrieves chunks of the request body. [edofic]ActionEnvhad agetBodyChunkfield added (inWeb.Scotty.Internal.Types)RequestBodyStateandBodyPartiallyStreamedadded toWeb.Scotty.Internal.Types
-
jsonDatausesaeson’seitherDecodeinstead of justdecode[k-bx]
0.9.1
- text/html/json only set Content-Type header when not already set
0.9.0
-
Add
charset=utf-8toContent-Typefortext,htmlandjson -
Assume HTTP status 500 for
defaultHandler -
Remove deprecated
sourcemethod. -
No longer depend on conduit.
0.8.2
-
Bump
aesonupper bound -
Fix
mtlrelated deprecation warnings
0.8.1
-
Export internal types
-
Added
MonadBase,MonadTransControlandMonadBaseControlinstances forActionT
0.8.0
-
Upgrade to wai/wai-extra/warp 3.0
-
No longer depend on conduit-extra.
-
The
sourceresponse method has been deprecated in favor of a newstreamresponse, matching changes in WAI 3.0. -
Removed the deprecated
reqHeaderfunction.
0.7.3
- Bump upper bound for case-insensitive, mtl and transformers.
0.7.2
- Bump lower bound on conduit, add conduit-extra to cabal build depends.
0.7.1
- Default warp settings now use
setFdCacheDuration 0to work around a warp issue where file changes are not getting picked up.
0.7.0
-
Renamed
reqHeadertoheader. Addedheadersfunction to get all headers. -
Changed
MonadIOinstance forActionTsuch that IO exceptions are lifted intoScottyErrors viastringError. -
Make
Boolparsing case-insensitive. Goal: support both Haskell’s True/False and Javascript’s true/false. Thanks to Ben Gamari for suggesting this. -
Bump
aeson/textupper bounds. -
Bump
wai/wai-extra/warpbounds, including new lower bound forwarp, which fixes a security issue related to Slowloris protection.
0.6.2
- Bump upper bound for
text.
0.6.1
- Match changes in
wai-extra.
0.6.0
-
The Scotty transformers (
ScottyTandActionT) are now parameterized over a custom exception type, allowing one to extend Scotty’sErrorTlayer with something richer thanTexterrors. See theexceptionsexample for use.ScottyMandActionMremain specialized toTextexceptions for simplicity. -
Both monads are now instances of
FunctorandApplicative. -
There is a new
cookiesexample. -
Internals brought up-to-date with WAI 2.0 and related packages.
0.5.0
-
The Scotty monads (
ScottyMandActionM) are now monad transformers, allowing Scotty applications to be embedded in arbitraryMonadIOs. The old API continues to be exported fromWeb.Scottywhere:type ScottyM = ScottyT IO type ActionM = ActionT IOThe new transformers are found in
Web.Scotty.Trans. See theglobalstateexample for use. Special thanks to Dan Frumin (co-dan) for much of the legwork here. -
Added support for HTTP PATCH method.
-
Removed lambda action syntax. This will return when we have a better story for typesafe routes.
-
reqHeader :: Text -> ActionM Text==>reqHeader :: Text -> ActionM (Maybe Text) -
New
rawmethod to set body to a rawByteString -
Parse error thrown by
jsonDatanow includes the body it couldn’t parse. -
headersplit intosetHeaderandaddHeader. The former replaces a response header (original behavior). The latter adds a header (useful for multipleSet-Cookies, for instance).