nested-routes: Declarative, compositional Wai responses

[ bsd3, library, web ] [ Propose Tags ]
This version is deprecated.

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"

Downloads

Maintainer's Corner

Package maintainers

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-14T04:06:01Z
Distributions
Reverse Dependencies 2 direct, 0 indirect [details]
Downloads 24058 total (113 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]