snap-web-routes (empty) → 0.1.0.0
raw patch · 6 files changed
+215/−0 lines, 6 filesdep +basedep +heistdep +mtlsetup-changed
Dependencies added: base, heist, mtl, snap, snap-core, text, web-routes, xmlhtml
Files
- LICENSE +30/−0
- README.md +7/−0
- Setup.hs +2/−0
- snap-web-routes.cabal +35/−0
- src/Snap/Web/Routes.hs +129/−0
- src/Snap/Web/Routes/Heist.hs +12/−0
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright (c) 2014, Luke Randall++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++ * Redistributions of source code must retain the above copyright+ notice, this list of conditions and the following disclaimer.++ * Redistributions in binary form must reproduce the above+ copyright notice, this list of conditions and the following+ disclaimer in the documentation and/or other materials provided+ with the distribution.++ * Neither the name of Luke Randall nor the names of other+ contributors may be used to endorse or promote products derived+ from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,7 @@+# snap-web-routes: Type safe URLs for Snap++`snap-web-routes` provides type safe URLs for Snap using [`web routes`](http://hackage.haskell.org/package/web-routes).++# How to use++See `Snap.Web.Routes` for instructions.
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ snap-web-routes.cabal view
@@ -0,0 +1,35 @@+name: snap-web-routes+version: 0.1.0.0+synopsis: Type safe URLs for Snap+description: Type safe URL generation and routing for Snap using web-routes+homepage: http://github.com/lukerandall/snap-web-routes+license: BSD3+license-file: LICENSE+author: Luke Randall+maintainer: luke.randall@gmail.com+category: Web, Snap+build-type: Simple+cabal-version: >=1.10++extra-source-files:+ LICENSE,+ README.md++library+ hs-source-dirs: src++ exposed-modules:+ Snap.Web.Routes+ Snap.Web.Routes.Heist++ build-depends:+ base >= 4.4 && < 5,+ heist >= 0.13 && < 0.14,+ mtl >= 2 && < 3,+ snap-core >= 0.9 && < 0.11,+ snap >= 0.13 && < 0.14,+ text >= 0.11 && < 1.2,+ web-routes >= 0.27 && < 0.28,+ xmlhtml >= 0.1++ default-language: Haskell2010
+ src/Snap/Web/Routes.hs view
@@ -0,0 +1,129 @@+{-|++This module provides a ready to use implementation of `web-routes` for Snap.++To get going, you'll need to add a few things to `Application.hs`.++> {-# LANGUAGE DeriveGeneric #-}+> {-# LANGUAGE FlexibleInstances #-}+> {-# LANGUAGE TypeFamilies #-}++DeriveGeneric is used to derive the `PathInfo` instance for your URL data type,+the rest are needed by `web-routes`.++> import Data.Text (Text)+> import Snap.Web.Routes++"Snap.Web.Routes" exports the data types needed to define your `PathInfo` and+`MonadRoute` instances below.++> data AppUrl+> = Count Int+> | Echo Text+> | Paths [Text]+> deriving (Generic)++Define your application's URL data type. Deriving a `Generic` instance gives+you a `PathInfo` instance for free.++> data App = App+> { _routeFn :: AppUrl -> [(Text, Maybe Text)] -> Text+> }++Extend your App type to include a routing function.++> instance PathInfo AppUrl++Get your free PathInfo instance. Alternatives are to use `web-routes-th` or+implement PathInfo yourself.++> instance MonadRoute (Handler App App) where+> type URL (Handler App App) = AppUrl+> askRouteFn = gets _routeFn++Define your MonadRoute instance. In particular, `type URL (Handler App App)`+must be set to your URL data type defined above and `askRouteFn` should point+to the routing function you added to your App type.++Moving on to `Site.hs`.++> import Snap.Web.Routes++Snap.Web.Routes provides a convenience router function you'll need.++> routes :: [(ByteString, Handler App App ())]+> routes = [ ("", serveDirectory "static")+> , ("", routeWith routeAppUrl)+> ]++Add your routes to the bottom of the routes list using routeWith.++> routeAppUrl :: AppUrl -> Handler App App ()+> routeAppUrl appUrl =+> case appUrl of+> (Count n) -> writeText $ ("Count = " `T.append` (T.pack $ show n))+> (Echo text) -> echo text+> (Paths ps) -> writeText $ T.intercalate " " ps++> echo :: T.Text -> Handler App App ()+> echo msg = heistLocal (bindString "message" msg) $ render "echo"++Define the handler for each data constructor in your URL data type.++> app :: SnapletInit App App+> app = makeSnaplet "app" "An example application with snap-web-routes." Nothing $ do+> addRoutes routes+> return $ App renderRoute++Lastly, add the routing function to your app. If you prefixed the routes in routeWith:++> , ("/prefix", routeWith routeAppUrl)++then use `renderRouteWithPrefix` instead:++> return . App $ renderRouteWithPrefix "/prefix"++|-}++{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TypeFamilies #-}++module Snap.Web.Routes+ ( renderRoute+ , renderRouteWithPrefix+ , routeWith+ , heistUrl+ , gets+ , Generic+ , MonadRoute(..)+ , PathInfo(..)+ ) where++import Control.Monad.State (lift, gets)+import Data.Text (Text, append, pack)+import Heist (HeistT)+import Snap.Core+import Snap.Web.Routes.Heist+import Snap.Snaplet+import Web.Routes+++instance (MonadRoute m) => MonadRoute (HeistT n m) where+ type URL (HeistT n m) = URL m+ askRouteFn = lift askRouteFn+++routeWith :: (PathInfo url, MonadSnap m) => (url -> m ()) -> m ()+routeWith router =+ do rq <- getRequest+ case fromPathInfo $ rqPathInfo rq of+ (Left e) -> writeText (pack e)+ (Right url) -> router url+++renderRoute :: PathInfo url => url -> [(Text, Maybe Text)] -> Text+renderRoute = renderRouteWithPrefix ""+++renderRouteWithPrefix :: PathInfo url => Text -> url -> [(Text, Maybe Text)] -> Text+renderRouteWithPrefix prefix url params = prefix `append` toPathInfoParams url params
+ src/Snap/Web/Routes/Heist.hs view
@@ -0,0 +1,12 @@+module Snap.Web.Routes.Heist+ ( heistUrl+ ) where++import Text.XmlHtml hiding (render)+import Web.Routes+++heistUrl :: MonadRoute m => URL m -> m [Node]+heistUrl u =+ do t <- showURL u+ return [TextNode t]