packages feed

webcrank-wai (empty) → 0.1

raw patch · 12 files changed

+393/−0 lines, 12 filesdep +basedep +bytestringdep +exceptionssetup-changed

Dependencies added: base, bytestring, exceptions, lens, mtl, unix-compat, unordered-containers, wai, wai-lens, webcrank, webcrank-dispatch

Files

+ .gitignore view
@@ -0,0 +1,2 @@+dist+examples/dist
+ .travis.yml view
@@ -0,0 +1,46 @@+# From https://github.com/hvr/multi-ghc-travis++# NB: don't set `language: haskell` here++# The following enables several GHC versions to be tested; often it's enough to test only against the last release in a major GHC version. Feel free to omit lines listings versions you don't need/want testing for.+env:+ - CABALVER=1.18 GHCVER=7.6.3+ - CABALVER=1.18 GHCVER=7.8.3+ - CABALVER=1.22 GHCVER=7.10.1+ - CABALVER=head GHCVER=head   # see section about GHC HEAD snapshots++matrix:+  allow_failures:+   - env: CABALVER=head GHCVER=head++# Note: the distinction between `before_install` and `install` is not important.+before_install:+ - travis_retry sudo add-apt-repository -y ppa:hvr/ghc+ - travis_retry sudo apt-get update+ - travis_retry sudo apt-get install cabal-install-$CABALVER ghc-$GHCVER # see note about happy/alex+ - export PATH=/opt/ghc/$GHCVER/bin:/opt/cabal/$CABALVER/bin:$PATH++install:+ - cabal --version+ - echo "$(ghc --version) [$(ghc --print-project-git-commit-id 2> /dev/null || echo '?')]"+ - travis_retry cabal update+ - cabal install --only-dependencies --enable-tests --enable-benchmarks++# Here starts the actual work to be performed for the package under test; any command which exits with a non-zero exit code causes the build to fail.+script:+ - if [ -f configure.ac ]; then autoreconf -i; fi+ - cabal configure --enable-tests --enable-benchmarks -v2  # -v2 provides useful information for debugging+ - cabal build   # this builds all libraries and executables (including tests/benchmarks)+ - cabal test+ - cabal check+ - cabal sdist   # tests that a source-distribution can be generated++# The following scriptlet checks that the resulting source distribution can be built & installed+ - export SRC_TGZ=$(cabal info . | awk '{print $2 ".tar.gz";exit}') ;+   cd dist/;+   if [ -f "$SRC_TGZ" ]; then+      cabal install --force-reinstalls "$SRC_TGZ";+   else+      echo "expected '$SRC_TGZ' not found";+      exit 1;+   fi
+ HLint.hs view
@@ -0,0 +1,5 @@+import "hint" HLint.Default+import "hint" HLint.Generalise++ignore "Use import/export shortcut"+
+ LICENSE view
@@ -0,0 +1,25 @@+Copyright (c) 2012, Webcrank, Mark Hibberd and others.++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. 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.+3. The name of the author may not be used to endorse or promote products+   derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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,4 @@+# Webcrank on Wai [![TravisCI](https://travis-ci.org/webcrank/webcrank-wai.svg)](https://travis-ci.org/webcrank/webcrank-wai) [![Hackage](https://img.shields.io/hackage/v/webcrank-wai.svg?style=flat)](https://hackage.haskell.org/package/webcrank-wai)++A library for building [Webcrank](https://github.com/webcrank/webcrank.hs) [WAI](https://hackage.haskell.org/package/wai) `Application`s.+
+ Setup.hs view
@@ -0,0 +1,5 @@+#!/usr/bin/env runhaskell++import Distribution.Simple++main = defaultMain
+ examples/LICENSE view
@@ -0,0 +1,25 @@+Copyright (c) 2012, Webcrank, Mark Hibberd and others.++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions+are met:+1. Redistributions of source code must retain the above copyright+   notice, this list of conditions and the following disclaimer.+2. 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.+3. The name of the author may not be used to endorse or promote products+   derived from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 AUTHOR 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.
+ examples/Main.hs view
@@ -0,0 +1,63 @@+{-# LANGUAGE DataKinds #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}++module Main where++import Control.Applicative+import Control.Monad.State+import Control.Monad.Catch+import Data.Monoid+import Data.Text (Text)+import qualified Network.Wai.Handler.Warp as Warp++import Webcrank.Wai++data MyData = MyData String++newtype MyApp a = MyApp { unMyApp :: StateT MyData Wai a }+  deriving+    ( Functor+    , Applicative+    , Monad+    , MonadIO+    , MonadThrow+    , MonadCatch+    , MonadWai+    )++runMyApp :: MyApp a -> MyData -> Wai a+runMyApp = evalStateT . unMyApp++runMyAppF :: MyData -> MyApp a -> Wai a+runMyAppF = flip runMyApp++index :: Path '[]+index = ""++indexResource :: MonadIO m => Resource m+indexResource = resourceWithHtml $ return $ textBody $ mconcat+  [ "<h1>Welcome to Webcrank!</h1>"+  , "<a href=\""+  , renderRoute echoPath $ "Hello" .*. HNil+  , "\">Allow me to greet you properly</a>"+  ]++echoPath :: Path '[Text]+echoPath = "echo" </> var++echoResource :: Monad m => Text -> Resource m+echoResource t = resourceWithHtml $ return $ textBody $  mconcat ["<h1>", t, "</h1>"]++myApp+  :: Request+  -> (Response -> IO ResponseReceived)+  -> IO ResponseReceived+myApp = dispatch (runMyAppF (MyData "a")) $ mconcat+  [ index ==> indexResource+  , echoPath ==> echoResource+  ]++main :: IO ()+main = Warp.run 3000 myApp+
+ examples/Setup.hs view
@@ -0,0 +1,5 @@+#!/usr/bin/env runhaskell++import Distribution.Simple++main = defaultMain
+ examples/webcrank-wai-examples.cabal view
@@ -0,0 +1,28 @@+name:               webcrank-wai-examples+version:            0.0.1+license:            BSD3+license-file:       LICENCE+author:             Richard Wallace <rwallace@thewallacepack.net>+maintainer:         Richard Wallace <rwallace@thewallacepack.net>+copyright:          (c) 2015 Richard Wallace+synopsis:           Example WAI Application built with Webcrank+category:           Web+homepage:           https://github.com/webcrank/webcrank-wai+bug-reports:        https://github.com/webcrank/webcrank-wai/issues+cabal-version:      >= 1.8+build-type:         Simple++flag                small_base+  description:      Choose the new, split-up base package.++executable examples+  main-is:          Main.hs+  build-depends:    base                            >= 4.6 && < 5+                  , bytestring+                  , exceptions+                  , mtl+                  , text+                  , warp+                  , webcrank-wai++  ghc-options:      -Wall
+ src/Webcrank/Wai.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FunctionalDependencies #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE TemplateHaskell #-}+{-# LANGUAGE RankNTypes #-}++module Webcrank.Wai+  ( WaiResource+  , WaiCrankT+  , dispatch+  , HasRequest(..)+  , HasRequestDate(..)+  , WaiData+  , ReqData+  , module Webcrank+  , module Webcrank.Dispatch+  ) where++import Control.Applicative+import Control.Lens+import Control.Monad.Catch+import Control.Monad.RWS+import qualified Data.ByteString.Lazy as LBS+import qualified Data.HashMap.Strict as HashMap+import Data.Maybe+import Data.Traversable+import Network.Wai hiding (pathInfo, requestHeaders)+import Network.Wai.Lens+import System.PosixCompat.Time++import Webcrank+import Webcrank.Dispatch hiding (dispatch)+import qualified Webcrank.Dispatch as W+import Webcrank.ServerAPI hiding (handleRequest)+import qualified Webcrank.ServerAPI as API++-- | Holds the request and resource state during request processing.+data WaiData m = WaiData+  { _resourceData :: ResourceData m+  , _waiDataRequest :: Request+  , _waiDataRequestDate :: HTTPDate+  }++makeFields ''WaiData++instance HasResourceData (WaiData m) m where+  resourceData f ~(WaiData rd rq d) = fmap (\rd' -> WaiData rd' rq d) (f rd)++-- | Monad transformer that all resource functions will run in. Provides+-- the ability to read the WAI @'Request'@ inside resource functions.+newtype WaiCrankT m a =+  WaiCrankT { unWaiCrankT :: RWST (WaiData (WaiCrankT m)) LogData ReqData m a }+  deriving+    ( Functor+    , Applicative+    , Monad+    , MonadIO+    , MonadReader (WaiData (WaiCrankT m))+    , MonadState ReqData+    , MonadWriter LogData+    , MonadThrow+    , MonadCatch+    , MonadMask+    )++instance MonadTrans WaiCrankT where+  lift = WaiCrankT . lift++type WaiResource m = Resource (WaiCrankT m)++type WaiServerAPI m = ServerAPI (WaiCrankT m)++-- | Function for turning @'Dispatcher'@s into @'Application'@s.+-- A @run@ function must be provided for executing the application+-- logic.  In the simplest case, where @m@ is @IO@, this can just be+-- @'id'@.+dispatch+  :: (Applicative m, MonadIO m, MonadCatch m)+  => (forall a. m a -> IO a) -- ^ run+  -> Dispatcher (WaiResource m)+  -> Application+dispatch f d rq = f . dispatch' d rq++dispatch'+  :: (Applicative m, MonadIO m, MonadCatch m)+  => Dispatcher (WaiResource m)+  -> Request+  -> (Response -> IO ResponseReceived)+  -> m ResponseReceived+dispatch' d rq respond = maybe (sendNotFound respond) run disp where+  run r = handleRequest r rq respond+  disp = W.dispatch d (rq ^. pathInfo)++sendNotFound+  :: MonadIO m+  => (Response -> IO ResponseReceived)+  -> m ResponseReceived+sendNotFound respond = liftIO $ respond $ responseLBS notFound404 [] "404 Not Found"++runWaiCrankT+  :: (Applicative m, MonadCatch m, MonadIO m)+  => WaiCrankT m a+  -> WaiData (WaiCrankT m)+  -> m (a, ReqData, LogData)+runWaiCrankT w d = do+  runRWST (unWaiCrankT w) d newReqData++handleRequest+  :: (Applicative m, MonadCatch m, MonadIO m)+  => WaiResource m+  -> Request+  -> (Response -> IO ResponseReceived)+  -> m ResponseReceived+handleRequest r rq respond = do+  now <- liftIO epochTime+  let rd = WaiData (newResourceData api r) rq (epochTimeToHTTPDate now)+  res <- API.handleRequest (flip runWaiCrankT rd)+  liftIO $ respond $ waiRes res++waiRes :: (Status, HeadersMap, Maybe Body) -> Response+waiRes (s, hs, b) = responseLBS s (hdrs hs) (fromMaybe LBS.empty b) where+  hdrs = join . fmap sequenceA . HashMap.toList++api :: (Applicative m, Monad m) => WaiServerAPI m+api = ServerAPI+  { srvGetRequestMethod = requestMethod <$> view request+  , srvGetRequestHeader = \h ->+      preview (request . headers . value h)+  , srvGetRequestURI = undefined+  , srvGetRequestTime = view requestDate+  }
+ webcrank-wai.cabal view
@@ -0,0 +1,52 @@+name:               webcrank-wai+version:            0.1+license:            BSD3+license-file:       LICENSE+author:             Richard Wallace <rwallace@thewallacepack.net>+maintainer:         Richard Wallace <rwallace@thewallacepack.net>+copyright:          (c) 2015 Richard Wallace+synopsis:           Build a WAI Application from Webcrank Resources+category:           Web+homepage:           https://github.com/webcrank/webcrank-wai+bug-reports:        https://github.com/webcrank/webcrank-wai/issues+cabal-version:      >= 1.8+build-type:         Simple+description:+  Build a WAI Application from Webcrank Resources.++extra-source-files:+  .gitignore+  .travis.yml+  examples/LICENSE+  examples/webcrank-wai-examples.cabal+  examples/*.hs+  HLint.hs+  LICENSE+  README.md++source-repository   head+  type:             git+  location:         https://github.com/webcrank/webcrank-wai.git++flag                small_base+  description:      Choose the new, split-up base package.++library+  hs-source-dirs:   src++  exposed-modules:  Webcrank.Wai++  ghc-options:      -Wall++  build-depends:    base                            >= 4.6 && < 5+                  , bytestring+                  , exceptions+                  , lens+                  , mtl+                  , unix-compat+                  , unordered-containers+                  , wai+                  , wai-lens+                  , webcrank+                  , webcrank-dispatch+