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 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), 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 - 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, where d :: 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 a Map for HTTP verbs, likewise with text, 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 are Left and contain a VerbListenerT z (FileExtListenerT Response m ()) m (), while paths ending with a parser are Right and contain VerbListenerT 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"

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, constraints, containers, http-types, lucid, mtl, poly-arity (>=0.0.3), pred-trie (>=0.0.12), semigroups, text, transformers, wai, wai-extra [details]
License BSD-3-Clause
Author Athan Clark <athan.clark@gmail.com>
Maintainer Athan Clark <athan.clark@gmail.com>
Source repo head: git clone git://github.com/athanclark/nested-routes.git
Uploaded by athanclark at 2015-04-27T15:02:02Z
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]