nested-routes: Declarative, compositional Wai responses
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 and Regular Expressions directly in our routes, with our handlers reflecting their results. You can find more information on the demo.
As an example:
router :: Application router = route handlers where handlers = do handle o (Just $ get $ text "home") Nothing handle ("foo" </> "bar") (Just $ get $ text "foobar") $ Just $ handle (p ("baz", double) </> o) (Just $ \d -> get $ text $ LT.pack (show d) <> " bazs") Nothing handle (p ("num",double) </> o) (Just $ \d -> get $ text $ LT.pack $ show d) $ Just $ do handle "bar" (Just $ \d -> get $ do text $ (LT.pack $ show d) <> " bars") json $ (LT.pack $ show d) <> " bars!") Nothing handle (r ("email", mkRegex "(^[-a-zA-Z0-9_.]+@[-a-zA-Z0-9]+\\.[-a-zA-Z0-9.]+$)") </> o) (Just $ \d e -> get $ textOnly $ (LT.pack $ show d) <> " " <> (LT.pack $ show e)
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
), while p
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 actual Parser
. 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. 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, where d :: Double
.
Internally, we match against both the file extension and Accept headers in the HTTP request - the Accept header may override the file extension.
When we test our application:
λ> curl localhost:3000/ -H "Accept: text/plain, */*" ↪ "home"
requests may end with index
λ> curl localhost:3000/index -H "Accept: text/plain, */*" ↪ "home"
and specify the file extension
λ> curl localhost:3000/index.txt -H "Accept: text/plain, */*" ↪ "home"
each responding with the "closest" available file type
λ> curl localhost:3000/index.html -H "Accept: text/html, */*" ↪ "home"
λ> curl localhost:3000/foo/bar -H "Accept: text/plain, */*" ↪ "foobar"
λ> curl localhost:3000/foo/bar.txt -H "Accept: text/plain, */*" ↪ "foobar"
λ> curl localhost:3000/foo/bar/5678.5678 -H "Accept: text/plain, */*" ↪ "5678.5678 bazs"
λ> curl localhost:3000/1234.1234 -H "Accept: text/plain, */*" ↪ "1234.1234"
λ> curl localhost:3000/2e5 -H "Accept: text/plain, */*" ↪ "200000.0"
λ> curl localhost:3000/1234.1234/bar -H "Accept: text/plain, */*" ↪ "1234.1234 bars"
Modules
[Index]
- Web
- Routes
- Web.Routes.Nested
- Web.Routes.Nested.FileExtListener
- Web.Routes.Nested.FileExtListener.Blaze
- Web.Routes.Nested.FileExtListener.Builder
- Web.Routes.Nested.FileExtListener.ByteString
- Web.Routes.Nested.FileExtListener.Cassius
- Web.Routes.Nested.FileExtListener.Clay
- Web.Routes.Nested.FileExtListener.Json
- Web.Routes.Nested.FileExtListener.Julius
- Web.Routes.Nested.FileExtListener.Lucid
- Web.Routes.Nested.FileExtListener.Lucius
- Web.Routes.Nested.FileExtListener.Text
- Web.Routes.Nested.FileExtListener.Types
- Web.Routes.Nested.Types
- Web.Routes.Nested.VerbListener
- Web.Routes.Nested.FileExtListener
- Web.Routes.Nested
- Routes
Downloads
- nested-routes-2.1.0.tar.gz [browse] (Cabal source package)
- Package description (as included in the package)
Maintainer's Corner
For package maintainers and hackage trustees
Candidates
- No Candidates
Versions [RSS] | 0.0.1, 0.0.1.1, 0.0.2, 0.0.3.1, 0.1, 0.1.1, 0.2, 0.2.0.1, 0.2.0.2, 0.2.1, 0.2.2, 0.2.2.1, 0.2.2.2, 0.3, 0.3.1, 0.3.2, 0.3.2.1, 1.0, 1.0.0.1, 2.0.0, 2.0.1, 2.1.0, 2.2.0, 3.0.0, 3.0.0.1, 3.0.0.2, 3.1.0, 3.2.0, 4.0.0, 5.0.0, 6.0.0, 6.0.0.1, 6.1.0, 7.0.0, 7.1.0, 7.1.0.1, 7.1.1, 7.2.0, 7.2.1, 7.2.2, 8.0.0, 8.0.1, 8.0.2, 8.1.0, 8.2.0, 9.0.0, 9.0.0.1, 9.0.1.0, 9.0.1.1, 9.0.2, 10.0.0 (info) |
---|---|
Dependencies | aeson, attoparsec, base (>=4.6 && <5), blaze-html, bytestring, clay, composition, constraints, containers, http-media, http-types, lucid, mtl, poly-arity (>=0.0.4), pred-trie (>=0.1), regex-compat, semigroups, shakespeare, text, transformers, wai, wai-extra, wai-util, witherable [details] |
License | BSD-3-Clause |
Author | Athan Clark <athan.clark@gmail.com> |
Maintainer | Athan Clark <athan.clark@gmail.com> |
Category | Web |
Source repo | head: git clone git://github.com/athanclark/nested-routes.git |
Uploaded | by athanclark at 2015-05-14T14:55:11Z |
Distributions | |
Reverse Dependencies | 2 direct, 0 indirect [details] |
Downloads | 24892 total (19 in the last 30 days) |
Rating | (no votes yet) [estimated by Bayesian average] |
Your Rating | |
Status | Docs uploaded by user Build status unknown [no reports yet] |