nested-routes
Version 0.3 revision 0 uploaded by athanclark.
Package meta
- Synopsis
- Declarative, compositional Wai responses
- Description
A method to writing Wai responses
This library attempts to make it easier to write nice Wai response handlers by giving us a Sinatra/ Scotty-like syntax for declaring HTTP-verb oriented routes, in addition to file-extension handling and rose-tree like composition. Not only do we have literal route specification, like Scotty & Spock, but we can also embed Attoparsec parsers directly in our routes, with our handlers reflecting their results. As an example:
router :: Application router = route handlers where handlers = do handleLit o (Left $ get $ text "home") Nothing handleLit (l "foo" </> l "bar" </> o) (Left $ get $ text "foobar") $ Just $ handleParse (p ("baz",double) </> o) (\d -> Right $ get $ textOnly $ LT.pack (show d) `LT.append` " bazs") Nothing handleParse (p ("num",double) </> o) (\d -> Right $ get $ textOnly $ LT.pack $ show d) $ Just $ handleLit (l "bar" </> o) (\d -> Left $ get $ text $ (LT.pack $ show d) `LT.append` " bars") Nothing
The route specification syntax is a little strange right now -
l
specifies a "literal chunk" of a handlable url (ie -l "foo" </> l "bar" </> o
would represent the url/foo/bar
), whilep
represents a "parsable" url chunk, which expects a pair - the left element being merely a reference name for the parser during internal plumbing, and the right being the actualParser
.o
represents the end of a url string, and can be used alone in a handler to capture requests to the root path.Each route being handled needs some kind of content - that's where the
Either
stuff comes in to play. For every parsed url chunk, the route expects a function of arity matching 1-for-1 with the parsed contents. For example,d -> ...
in the demonstration above is such a function, whered :: Double
.We use the
Either
for a subtle reason - literal url strings may have a file extension, while url strings ending with a parser would not.get
,post
, etc. are all monadic expressions, accumulating aMap
for HTTP verbs, likewise withtext
,lucid
,json
,bytestring
etc., where they may also match a particular file extension.textOnly
and the other-Only
variants are not monadic, and simply give us a convenient unwrapper. Basically, url paths ending with a literal chunk areLeft
and contain aVerbListenerT z (FileExtListenerT Response m ()) m ()
, while paths ending with a parser areRight
and containVerbListenerT z Response m ()
.When we test our application:
λ> curl localhost:3000/ ↪ "home"
requests may end with index
λ> curl localhost:3000/index ↪ "home"
and specify the file extension
λ> curl localhost:3000/index.txt ↪ "home"
each responding with the "closest" available file type
λ> curl localhost:3000/index.html ↪ "home"
λ> curl localhost:3000/foo/bar ↪ "foobar"
λ> curl localhost:3000/foo/bar.txt ↪ "foobar"
λ> curl localhost:3000/foo/bar/5678.5678 ↪ "5678.5678 bazs"
λ> curl localhost:3000/1234.1234 ↪ "1234.1234"
λ> curl localhost:3000/2e5 ↪ "200000.0"
λ> curl localhost:3000/1234.1234/bar ↪ "1234.1234 bars"
- Author
- Athan Clark <athan.clark@gmail.com>
- Bug reports
- n/a
- Category
- n/a
- Copyright
- n/a
- Homepage
- n/a
- Maintainer
- Athan Clark <athan.clark@gmail.com>
- Package URL
- n/a
- Stability
- n/a