scotty
Haskell web framework inspired by Ruby's Sinatra, using WAI and Warp
https://github.com/scotty-web/scotty
LTS Haskell 23.1: | 0.22@rev:2 |
Stackage Nightly 2024-12-21: | 0.22@rev:2 |
Latest on Hackage: | 0.22@rev:2 |
scotty-0.22@sha256:b3c799b3c4896176342062c1140c290ffb9a8d81e6da2ea3e12f7a83cbda78d4,6013
Module documentation for 0.22
- Web
- Web.Scotty
- Web.Scotty.Cookie
- 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
main = scotty 3000 $
get "/:word" $ do
beam <- pathParam "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 the web application interface (WAI).
- Uses the very fast Warp webserver by default.
As for the name: Sinatra + Warp = Scotty.
Examples
Run /basic.hs to see Scotty in action:
runghc examples/basic.hs
Setting phasers to stun... (port 3000) (ctrl-c to quit)
Or equivalently with stack
:
stack exec -- scotty-basic
Once the server is running you can interact with it with curl or a browser:
curl localhost:3000
foobar
curl localhost:3000/foo_query?p=42
<h1>42</h1>
Additionally, the examples
directory shows a number of concrete use cases, e.g.
More Information
Tutorials and related projects can be found in the Scotty wiki.
Contributing
Feel free to ask questions or report bugs on the Github issue tracker.
Github issues are now (September 2023) labeled, so newcomers to the Haskell language can start with easy fix
ones and gradually progress to new feature
s, bug
s and R&D
:)
Package versions
Scotty adheres to the Package Versioning Policy.
FAQ
- Fails to compile regex-posix on Windows
- If you are using stack, add the following parameters to
stack.yaml
:-
extra-deps: - regex-posix-clib-2.7 flags: regex-posix: _regex-posix-clib: true
-
- If you are using cabal, update the
constraints
section ofcabal.project.local
as follows:-
constraints: regex-posix +_regex-posix-clib
-
- If you are using stack, add the following parameters to
Contributors
Copyright
(c) 2012-Present, Andrew Farmer and Scotty contributors
Changes
next [????.??.??]
0.22 [2024.03.09]
New
- add
instance Parsable UTCTime
(#250) - add
filesOpts
(#369). Form parameters and files are only parsed from the request body if needed;filesOpts
introduces options to customize upload limits, a mechanism to back uploads with temporary files based on resourcet, as well as a continuation-based syntax to process such temporary files.
Fixes
files
does not accept unbounded uploads anymore (see #183, #203), but likefilesOpts
it is backed by temporary files which are read back in memory and removed right away. The limits forfiles
are prescribed bydefaultParseBodyOptions
in wai-extra (#369).- Path parameters with value matching the parameter name prefixed by colon will properly populate
pathParams
with their literal value :/:param
will match/:param
and add aParam
with value("param", ":param")
(#301) - Accept text-2.1 (#364)
- Remove dependency upper bounds on
text
andbytestring
(#371) - When in ‘verbose’ mode any unhandled exceptions are printed to stderr as well (#374)
Breaking changes
- some ActionT API functions have now a MonadIO or MonadUnliftIO constraint rather than Monad reflecting that there is where request reading takes place. E.g.
files
has now a MonadUnliftIO constraint on its base monad. (#369) - the File type has now a type parameter to reflect whether it carries file contents or just a filepath pointing to the temp file (#369).
0.21 [2023.12.17]
New
- add
getResponseHeaders
,getResponseStatus
,getResponseContent
(#214) - add
captureParamMaybe
,formParamMaybe
,queryParamMaybe
(#322) - add
Web.Scotty.Trans.Strict
andWeb.Scotty.Trans.Lazy
(#334) - renamed
captureParam
,captureParamMaybe
, andcaptureParams
topathParam
,pathParamMaybe
,pathParams
respectively, keeping the old names as their synonyms (#344)
Deprecated
- deprecate
rescue
andliftAndCatchIO
(#332) - Deprecate
StatusError
,raise
andraiseStatus
(#351)
Fixes
- Reverted the
MonadReader
instance ofActionT
so that it inherits the base monad (#342) - Scotty’s API such as
queryParam
now throwsScottyException
rather thanStatusException
. Uncaught exceptions are handled byscottyExceptionHandler
, resembling the existing behaviour
Breaking changes
File
type: the first component of the tuple is strict text now (used to be lazy prior to 0.21) (#370)
Documentation
- Add doctest, refactor some inline examples into doctests (#353)
- document “
defaultHandler
only applies to endpoints defined after it” (#237)
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).
- Adds a new
nested
handler that allows you to place an entire WAI Application under a Scotty route (#233). - Disambiguate request parameters (#204). Adjust the
Env
type to have three[Param]
fields instead of one, addcaptureParam
,formParam
,queryParam
and the associatedcaptureParams
,formParams
,queryParams
. Add deprecation notices toparam
andparams
. - Add
Scotty.Cookie
module (#293). - Change body parsing behaviour such that calls to
next
don’t result in POST request bodies disappearing (#147). - (Internal) Remove unused type
RequestBodyState
(#313) - Rewrite
ActionT
using the “ReaderT pattern” (#310) https://www.fpcomplete.com/blog/readert-design-pattern/
Breaking:
- (#310) Introduce
unliftio
as a dependency, and base exception handling oncatch
. - (#310) Clarify the exception handling mechanism of ActionT, ScottyT.
rescue
changes signature to use properException
types rather than strings. RemoveScottyError
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 ofcatch
.ScottyT
andActionT
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.
- Allow building with
transformers-0.6.*
andmtl-2.3.*
. Because theMonadTrans t
class gained aforall m. Monad m => Monad (t m)
superclass intransformers-0.6.0.0
, theMonadTrans
andMonadTransControl
instances forActionT e
now have aScottyError e
instance context to match theMonad
instance.
0.12 [2020.05.16]
- Provide
MonadReader
andMonadState
instances forActionT
. - Add HTTP Status code as a field to
ActionError
, and add a sister function toraise
,raiseStatus
. This makes throwing a specific error code and exiting much cleaner, and avoids the strange defaulting to HTTP 500. This will make internal functions easier to implement with the right status codes ‘thrown’, such asjsonData
. - Correct http statuses returned by
jsonData
(#228). - Better error message when no data is provided to
jsonData
(#226). - Add
Semigroup
andMonoid
instances forActionT
andScottyT
- ScottyT: Use strict StateT instead of lazy
- Handle adjacent slashes in the request path as one (thanks @SkyWriter)
0.11.5 [2019.09.07]
- Allow building the test suite with
hspec-wai-0.10
.
0.11.4 [2019.05.02]
- Allow building with
base-4.13
(GHC 8.8).
0.11.3 [2019.01.08]
- Drop the test suite’s dependency on
hpc-coveralls
, which is unmaintained and does not build with GHC 8.4 or later.
0.11.2 [2018.07.02]
- Migrate from
Network
toNetwork.Socket
to avoid deprecation warnings.
0.11.1 [2018.04.07]
- Add
MonadThrow
andMonadCatch
instances forActionT
[abhinav] - Fix
matchAny
so that all methods are matched, not just standard ones [taphu]
0.11.0
- IO exceptions are no longer automatically turned into ScottyErrors by
liftIO
. UseliftAndCatchIO
to get that behavior. - New
finish
function. - Text values are now leniently decoded from ByteStrings.
- Added
MonadFail
instance forScottyT
- Lots of bound bumps on dependencies.
0.10.2
- Removed debug statement from routes
0.10.1
Parsable
instances forWord
,Word8
,Word16
,Word32
,Word64
[adamflott]Parsable
instances forInt8
,Int16
,Int32
,Int64
, andNatural
- Removed redundant
Monad
constraint onmiddleware
0.10.0
-
The monad parameters to
ScottyT
have been decoupled, causing the type of theScottyT
constructor to change. As a result,ScottyT
is no longer aMonadTrans
instance, and the type signatures ofscottyT
,scottyAppT
, andscottyOptsT
have been simplified. [ehamberg] -
socketDescription
no longer uses the deprecatedPortNum
constructor. Instead, it uses theShow
instance forPortNumber
. This changes the bytes from host to network order, so the output ofsocketDescription
could change. [ehamberg] -
Alternative
,MonadPlus
instances forActionT
-
scotty
now depends ontransformers-compat
. As a result,ActionT
now usesExceptT
, regardless of which version oftransformers
is used. As a result, several functions inWeb.Scotty.Trans
no longer require aScottyError
constraint, sinceExceptT
does not require anError
constraint (unlikeErrorT
). -
Added support for OPTIONS routes via the
options
function [alvare] -
Add
scottySocket
andscottySocketT
, exposing Warp Unix socket support [hakujin] -
Parsable
instance for lazyByteString
[tattsun] -
Added streaming uploads via the
bodyReader
function, which retrieves chunks of the request body. [edofic]ActionEnv
had agetBodyChunk
field added (inWeb.Scotty.Internal.Types
)RequestBodyState
andBodyPartiallyStreamed
added toWeb.Scotty.Internal.Types
-
jsonData
usesaeson
’seitherDecode
instead 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-8
toContent-Type
fortext
,html
andjson
-
Assume HTTP status 500 for
defaultHandler
-
Remove deprecated
source
method. -
No longer depend on conduit.
0.8.2
-
Bump
aeson
upper bound -
Fix
mtl
related deprecation warnings
0.8.1
-
Export internal types
-
Added
MonadBase
,MonadTransControl
andMonadBaseControl
instances forActionT
0.8.0
-
Upgrade to wai/wai-extra/warp 3.0
-
No longer depend on conduit-extra.
-
The
source
response method has been deprecated in favor of a newstream
response, matching changes in WAI 3.0. -
Removed the deprecated
reqHeader
function.
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 0
to work around a warp issue where file changes are not getting picked up.
0.7.0
-
Renamed
reqHeader
toheader
. Addedheaders
function to get all headers. -
Changed
MonadIO
instance forActionT
such that IO exceptions are lifted intoScottyError
s viastringError
. -
Make
Bool
parsing case-insensitive. Goal: support both Haskell’s True/False and Javascript’s true/false. Thanks to Ben Gamari for suggesting this. -
Bump
aeson
/text
upper bounds. -
Bump
wai
/wai-extra
/warp
bounds, 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 (
ScottyT
andActionT
) are now parameterized over a custom exception type, allowing one to extend Scotty’sErrorT
layer with something richer thanText
errors. See theexceptions
example for use.ScottyM
andActionM
remain specialized toText
exceptions for simplicity. -
Both monads are now instances of
Functor
andApplicative
. -
There is a new
cookies
example. -
Internals brought up-to-date with WAI 2.0 and related packages.
0.5.0
-
The Scotty monads (
ScottyM
andActionM
) are now monad transformers, allowing Scotty applications to be embedded in arbitraryMonadIO
s. The old API continues to be exported fromWeb.Scotty
where:type ScottyM = ScottyT IO type ActionM = ActionT IO
The new transformers are found in
Web.Scotty.Trans
. See theglobalstate
example 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
raw
method to set body to a rawByteString
-
Parse error thrown by
jsonData
now includes the body it couldn’t parse. -
header
split intosetHeader
andaddHeader
. The former replaces a response header (original behavior). The latter adds a header (useful for multipleSet-Cookie
s, for instance).