nested-routes 8.0.1 → 8.0.2
raw patch · 8 files changed
+156/−353 lines, 8 filesdep −nested-routesdep −warpdep ~basedep ~poly-aritydep ~pred-setPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies removed: nested-routes, warp
Dependency ranges changed: base, poly-arity, pred-set, pred-trie, wai-middleware-content-type, wai-middleware-verbs, wai-transformers
API changes (from Hackage documentation)
- Web.Routes.Nested: extractAuth :: (Monad m, MonadIO m, MonadThrow m) => (Request -> [sec] -> m ()) -> Request -> RouterT x (SecurityToken sec) m a -> m ()
+ Web.Routes.Nested: extractAuth :: (MonadIO m, MonadThrow m) => (Request -> [sec] -> m ()) -> Request -> RouterT x (SecurityToken sec) m a -> m ()
- Web.Routes.Nested: extractAuthSym :: (Monad m, MonadIO m) => [Text] -> RouterT x (SecurityToken sec) m a -> m [sec]
+ Web.Routes.Nested: extractAuthSym :: (MonadIO m) => [Text] -> RouterT x (SecurityToken sec) m a -> m [sec]
- Web.Routes.Nested: extractMatch :: (Monad m, MonadIO m) => [Text] -> RouterT r sec m a -> m (Maybe r)
+ Web.Routes.Nested: extractMatch :: (MonadIO m) => [Text] -> RouterT r sec m a -> m (Maybe r)
- Web.Routes.Nested: extractMatchAny :: (Monad m, MonadIO m) => [Text] -> RouterT r sec m a -> m (Maybe r)
+ Web.Routes.Nested: extractMatchAny :: (MonadIO m) => [Text] -> RouterT r sec m a -> m (Maybe r)
- Web.Routes.Nested: extractNearestVia :: (MonadIO m, Monad m) => [Text] -> (RouterT r sec m a -> m (RootedPredTrie Text r)) -> RouterT r sec m a -> m (Maybe r)
+ Web.Routes.Nested: extractNearestVia :: (MonadIO m) => [Text] -> (RouterT r sec m a -> m (RootedPredTrie Text r)) -> RouterT r sec m a -> m (Maybe r)
- Web.Routes.Nested: match :: (Monad m, xs' ~ CatMaybes xs, Match xs' xs childContent resultContent) => UrlChunks xs -> childContent -> RouterT resultContent sec m ()
+ Web.Routes.Nested: match :: (Monad m, Match xs' xs childContent resultContent) => UrlChunks xs -> childContent -> RouterT resultContent sec m ()
- Web.Routes.Nested: matchGroup :: (Monad m, xs' ~ CatMaybes xs, MatchGroup xs' xs childContent resultContent childSec resultSec) => UrlChunks xs -> RouterT childContent childSec m () -> RouterT resultContent resultSec m ()
+ Web.Routes.Nested: matchGroup :: (Monad m, MatchGroup xs' xs childContent resultContent childSec resultSec) => UrlChunks xs -> RouterT childContent childSec m () -> RouterT resultContent resultSec m ()
- Web.Routes.Nested: route :: (Monad m, MonadIO m) => RouterT (MiddlewareT m) sec m a -> MiddlewareT m
+ Web.Routes.Nested: route :: (MonadIO m) => RouterT (MiddlewareT m) sec m a -> MiddlewareT m
- Web.Routes.Nested: routeAuth :: (Monad m, MonadIO m, MonadThrow m) => (Request -> [sec] -> m ()) -> RouterT (MiddlewareT m) (SecurityToken sec) m a -> MiddlewareT m
+ Web.Routes.Nested: routeAuth :: (MonadIO m, MonadThrow m) => (Request -> [sec] -> m ()) -> RouterT (MiddlewareT m) (SecurityToken sec) m a -> MiddlewareT m
- Web.Routes.Nested: type Match xs' xs childContent resultContent = (Singleton (UrlChunks xs) childContent (RootedPredTrie Text resultContent), ArityTypeListIso childContent xs' resultContent)
+ Web.Routes.Nested: type Match xs' xs childContent resultContent = (xs' ~ CatMaybes xs, Singleton (UrlChunks xs) childContent (RootedPredTrie Text resultContent), ArityTypeListIso childContent xs' resultContent)
- Web.Routes.Nested.Match: f_ :: Text -> EitherUrlChunk (Just Text)
+ Web.Routes.Nested.Match: f_ :: Text -> EitherUrlChunk ( 'Just Text)
- Web.Routes.Nested.Match: file_ :: Text -> EitherUrlChunk (Just Text)
+ Web.Routes.Nested.Match: file_ :: Text -> EitherUrlChunk ( 'Just Text)
- Web.Routes.Nested.Match: l_ :: Text -> EitherUrlChunk Nothing
+ Web.Routes.Nested.Match: l_ :: Text -> EitherUrlChunk 'Nothing
- Web.Routes.Nested.Match: literal_ :: Text -> EitherUrlChunk Nothing
+ Web.Routes.Nested.Match: literal_ :: Text -> EitherUrlChunk 'Nothing
- Web.Routes.Nested.Match: p_ :: Text -> Parser r -> EitherUrlChunk (Just r)
+ Web.Routes.Nested.Match: p_ :: Text -> Parser r -> EitherUrlChunk ( 'Just r)
- Web.Routes.Nested.Match: parse_ :: Text -> Parser r -> EitherUrlChunk (Just r)
+ Web.Routes.Nested.Match: parse_ :: Text -> Parser r -> EitherUrlChunk ( 'Just r)
- Web.Routes.Nested.Match: pred_ :: Text -> (Text -> Maybe r) -> EitherUrlChunk (Just r)
+ Web.Routes.Nested.Match: pred_ :: Text -> (Text -> Maybe r) -> EitherUrlChunk ( 'Just r)
- Web.Routes.Nested.Match: r_ :: Text -> Regex -> EitherUrlChunk (Just [String])
+ Web.Routes.Nested.Match: r_ :: Text -> Regex -> EitherUrlChunk ( 'Just [String])
- Web.Routes.Nested.Match: regex_ :: Text -> Regex -> EitherUrlChunk (Just [String])
+ Web.Routes.Nested.Match: regex_ :: Text -> Regex -> EitherUrlChunk ( 'Just [String])
- Web.Routes.Nested.Types: action :: Monad m => MonadBaseControl IO m stM => Extractable stM => ActionT m () -> MiddlewareT m
+ Web.Routes.Nested.Types: action :: MonadBaseControl IO m stM => Extractable stM => ActionT m () -> MiddlewareT m
Files
- examples/Main.hs +0/−152
- nested-routes.cabal +102/−141
- src/Web/Routes/Nested.hs +21/−26
- src/Web/Routes/Nested/Match.hs +7/−7
- src/Web/Routes/Nested/Types.hs +14/−14
- test/Test.hs +2/−3
- test/Web/Routes/NestedSpec.hs +3/−3
- test/Web/Routes/NestedSpec/Basic.hs +7/−7
− examples/Main.hs
@@ -1,152 +0,0 @@-{-# LANGUAGE- OverloadedStrings- , ScopedTypeVariables- , FlexibleContexts- , DeriveDataTypeable- , DataKinds- #-}---module Main where--import Web.Routes.Nested-import Network.Wai.Trans-import Network.Wai.Handler.Warp-import Network.HTTP.Types-import Text.Regex-import qualified Data.Text as T-import qualified Data.Text.Lazy as LT-import Data.Attoparsec.Text hiding (match)-import Data.Monoid-import Data.Typeable-import Control.Monad.IO.Class-import Control.Monad.Catch-import Control.Monad.Trans---defApp :: Application-defApp _ respond = respond- $ textOnly "404 :(" status404 []--main :: IO ()-main = run 3000 $- (routeAuth authorize routes- `catchMiddlewareT` handleUploadError- `catchMiddlewareT` handleAuthError- ) defApp- where- handleUploadError u = fileExtsToMiddleware $- overFileExts [Text] (mapStatus $ const status400) $- case u of- NoChunkedBody -> text "No chunked body allowed!"- UploadTooLarge -> text "Upload too large"-- handleAuthError e = fileExtsToMiddleware $- overFileExts [Text] (mapStatus $ const status400) $- case e of- NeedsAuth -> text "Authentication needed"---- | A set of symbolic security roles-data AuthRole = AuthRole- deriving (Show, Eq)---- | The error thrown during authentication or authorization.------ I would encourage other security-related error schemes:------ - one data type for user authority errors - like when a logged-in user tries to access--- the admin console--- - one for types of failed authentication, during login (user doesn't exist,--- incorrect password, etc.)--- - one for malicious attacks - for instance if someone has tried (and failed) to login--- 5 times in the last minute, or multiple requests to the same resource-data AuthError = NeedsAuth- deriving (Show, Eq, Typeable)--instance Exception AuthError---- | Simple function that returns a response modification function - like--- something that adds to the response headers - to maintain a session cookie,--- for instance.------ You can use 'Control.Monad.Catch.throwM' to throw arbitrary errors, but--- you should also catch them with 'Network.Wai.Trans.catchMiddlewareT' to--- avoid runtime exceptions.-authorize :: ( Monad m- , MonadThrow m- ) => Request -> [AuthRole] -> m ()-authorize req ss | null ss = return ()- | otherwise = throwM NeedsAuth---- | The error thrown during the uploading function-data UploadError = NoChunkedBody- | UploadTooLarge- deriving (Show, Typeable)--instance Exception UploadError---routes :: ( MonadIO m- , MonadThrow m- ) => HandlerT (MiddlewareT m) (SecurityToken AuthRole) m ()-routes = do- matchHere (action rootHandle)- matchGroup (l_ "foo" </> o_) $ do- matchHere (action fooHandle)- auth AuthRole DontProtectHere- match (l_ "bar" </> o_) (action barHandle)- match (p_ "double" double </> o_) doubleHandle- match emailRoute emailHandle- match (l_ "baz" </> o_) (\app req -> action (bazHandle req) app req)- matchAny (action notFoundHandle)- where- rootHandle :: MonadIO m => ActionT m ()- rootHandle =- get $ do- text "Home"- json ("Home" :: T.Text)-- -- `/foo`- fooHandle :: MonadIO m => ActionT m ()- fooHandle = get $ text "foo!"-- -- `/foo/bar`- barHandle :: MonadIO m => ActionT m ()- barHandle =- get $ do- text "bar!"- json ("json bar!" :: T.Text)-- -- `/foo/1234e12`, uses attoparsec- doubleHandle :: MonadIO m => Double-> MiddlewareT m- doubleHandle d = action $ get $ text $ LT.pack (show d) <> " foos"-- -- `/athan@foo.com`- emailRoute :: UrlChunks '[ 'Just [String] ]- emailRoute = r_ "email" (mkRegex "(^[-a-zA-Z0-9_.]+@[-a-zA-Z0-9]+\\.[-a-zA-Z0-9.]+$)") </> o_-- emailHandle :: MonadIO m => [String] -> MiddlewareT m- emailHandle e = action $ get $ text $ LT.pack (show e) <> " email"-- -- `/baz- bazHandle :: ( MonadIO m- , MonadThrow m- ) => Request -> ActionT m ()- bazHandle req = do- get $ text "baz!"- post $ do- lift $ uploader req- text "uploaded!"- where- uploader :: (MonadIO m, MonadThrow m) => Request -> m ()- uploader req =- case requestBodyLength req of- ChunkedBody -> throwM NoChunkedBody- KnownLength l | l > 1024 -> throwM UploadTooLarge- | otherwise -> liftIO $ print =<< strictRequestBody req--- notFoundHandle :: MonadIO m => ActionT m ()- notFoundHandle = get $- overFileExts [Text] (mapStatus $ const status400) $- text "Not Found :("
nested-routes.cabal view
@@ -1,145 +1,106 @@-Name: nested-routes-Version: 8.0.1-Author: Athan Clark <athan.clark@gmail.com>-Maintainer: Athan Clark <athan.clark@gmail.com>-License: BSD3-License-File: LICENSE-Synopsis: Declarative, compositional Wai responses-Category: Web-Description:- A method to writing Wai responses- .- This library attempts to make it easier to write nice Wai response handlers- by giving us a Sinatra/- <https://hackage.haskell.org/package/scotty 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- <https://hackage.haskell.org/package/scotty Scotty> &- <https://hackage.haskell.org/package/spock Spock>, but we- can also embed- <https://hackage.haskell.org/package/attoparsec Attoparsec>- parsers and <https://hackage.haskell.org/package/regex-compat Regular Expressions>- /directly/ in our routes, with our handlers- reflecting their results.-Cabal-Version: >= 1.10-Build-Type: Simple---Flag Example- Description: Build the trivial example.- Default: False--Library- Default-Language: Haskell2010- HS-Source-Dirs: src- GHC-Options: -Wall- Exposed-Modules: Web.Routes.Nested- Web.Routes.Nested.Match- Web.Routes.Nested.Types- Build-Depends: base >= 4.8 && < 5- , attoparsec- , bifunctors- , bytestring- , errors- , exceptions- , extractable-singleton- , hashable- , hashtables- , monad-control-aligned- , mtl- , poly-arity >= 0.0.7- , pred-set >= 0.0.1- , pred-trie >= 0.5.1- , regex-compat- , semigroups- , text- , transformers- , tries- , unordered-containers- , wai-transformers >= 0.0.7- , wai-middleware-content-type >= 0.5.0.1- , wai-middleware-verbs >= 0.3.1---Test-Suite test- Type: exitcode-stdio-1.0- Default-Language: Haskell2010- HS-Source-Dirs: test- GHC-Options: -Wall -threaded- Main-Is: Test.hs- Other-Modules: Spec- Web.Routes.NestedSpec- Web.Routes.NestedSpec.Basic- Build-Depends: base- , nested-routes- , attoparsec- , bytestring- , composition-extra- , errors- , exceptions- , hashable- , hashtables- , HSet- , http-types- , mtl- , poly-arity- , pred-trie- , pred-set- , regex-compat- , semigroups- , text- , transformers- , tries- , unordered-containers- , wai-transformers- , wai-middleware-content-type- , wai-middleware-verbs- , hspec- , hspec-wai- , tasty- , tasty-hspec+-- This file has been generated from package.yaml by hpack version 0.21.2.+--+-- see: https://github.com/sol/hpack+--+-- hash: 3cba23da53b9eb7a5d98a85f0bdb6467464282f0dfcd97e2e82f38e36ffd4b6b +name: nested-routes+version: 8.0.2+synopsis: Declarative, compositional Wai responses+description: This library attempts to make it easier to write nice Wai response handlers by giving us a Sinatra/ <https://hackage.haskell.org/package/scotty 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 <https://hackage.haskell.org/package/scotty Scotty> & <https://hackage.haskell.org/package/spock Spock>, but we can also embed <https://hackage.haskell.org/package/attoparsec Attoparsec> parsers and <https://hackage.haskell.org/package/regex-compat Regular Expressions> /directly/ in our routes, with our handlers reflecting their results.+category: Web+homepage: https://github.com/athanclark/nested-routes#readme+bug-reports: https://github.com/athanclark/nested-routes/issues+maintainer: Athan Clark <athan.clark@gmail.com>+license: BSD3+license-file: LICENSE+build-type: Simple+cabal-version: >= 1.10 -Executable example- if flag(Example)- Buildable: True- else- Buildable: False- Default-Language: Haskell2010- HS-Source-Dirs: src- , examples- GHC-Options: -Wall -threaded- Main-Is: Main.hs- Other-Modules: Web.Routes.Nested- Web.Routes.Nested.Types- Web.Routes.Nested.Match- Build-Depends: base- , nested-routes >= 7- , attoparsec- , bytestring- , composition-extra- , errors- , exceptions- , hashable- , hashtables- , HSet- , http-types- , mtl- , poly-arity- , pred-set- , pred-trie- , regex-compat- , semigroups- , text- , transformers- , tries- , unordered-containers- , wai-transformers- , wai-middleware-content-type- , wai-middleware-verbs- , warp+source-repository head+ type: git+ location: https://github.com/athanclark/nested-routes +library+ exposed-modules:+ Web.Routes.Nested+ Web.Routes.Nested.Match+ Web.Routes.Nested.Types+ other-modules:+ Paths_nested_routes+ hs-source-dirs:+ src+ ghc-options: -Wall+ build-depends:+ attoparsec+ , base >=4.9 && <5+ , bifunctors+ , bytestring+ , errors+ , exceptions+ , extractable-singleton+ , hashable+ , hashtables+ , monad-control-aligned+ , mtl+ , poly-arity >=0.0.7+ , pred-set >=0.0.1+ , pred-trie >=0.5.1+ , regex-compat+ , semigroups+ , text+ , transformers+ , tries+ , unordered-containers+ , wai-middleware-content-type >=0.5.0.1+ , wai-middleware-verbs >=0.3.1+ , wai-transformers >=0.0.7+ default-language: Haskell2010 -Source-Repository head- Type: git- Location: https://github.com/athanclark/nested-routes.git+test-suite spec+ type: exitcode-stdio-1.0+ main-is: Test.hs+ other-modules:+ Spec+ Web.Routes.NestedSpec+ Web.Routes.NestedSpec.Basic+ Web.Routes.Nested+ Web.Routes.Nested.Match+ Web.Routes.Nested.Types+ Paths_nested_routes+ hs-source-dirs:+ test+ src+ ghc-options: -Wall+ build-depends:+ HSet+ , attoparsec+ , base+ , bifunctors+ , bytestring+ , composition-extra+ , errors+ , exceptions+ , extractable-singleton+ , hashable+ , hashtables+ , hspec+ , hspec-wai+ , http-types+ , monad-control-aligned+ , mtl+ , poly-arity+ , pred-set+ , pred-trie+ , regex-compat+ , semigroups+ , tasty+ , tasty-hspec+ , text+ , transformers+ , tries+ , unordered-containers+ , wai-middleware-content-type+ , wai-middleware-verbs+ , wai-transformers+ default-language: Haskell2010
src/Web/Routes/Nested.hs view
@@ -75,9 +75,11 @@ , module Network.Wai.Middleware.ContentType ) where +import Web.Routes.Nested.Match (UrlChunks, origin_) import Web.Routes.Nested.Match+import Web.Routes.Nested.Types (RouterT, execRouterT, Tries (..), ExtrudeSoundly) import Web.Routes.Nested.Types-import Network.Wai.Trans+import Network.Wai.Trans (MiddlewareT, Request, pathInfo) import Network.Wai.Middleware.Verbs import Network.Wai.Middleware.ContentType hiding (responseStatus, responseHeaders, responseData) @@ -88,22 +90,24 @@ import Data.Trie.HashMap (HashMapStep (..), HashMapChildren (..)) import Data.List.NonEmpty (NonEmpty (..), fromList) import qualified Data.Text as T-import Data.Hashable-import qualified Data.HashMap.Strict as HM-import Data.Monoid-import Data.Function.Poly-import Data.Bifunctor (bimap)+import Data.Hashable (Hashable)+import qualified Data.HashMap.Strict as HM+import Data.Monoid ((<>), First (..))+import Data.Function.Poly (ArityTypeListIso)+import Data.Bifunctor (bimap) import qualified Control.Monad.State as S-import Control.Monad.Catch-import Control.Monad.Trans-import Control.Arrow-import Control.Monad.ST+import Control.Monad.Catch (MonadThrow)+import Control.Monad.Trans (MonadTrans (..))+import Control.Monad.IO.Class (MonadIO (..))+import Control.Arrow (first)+import Control.Monad.ST (stToIO) -- | The constraints necessary for 'match'. type Match xs' xs childContent resultContent =- ( Singleton (UrlChunks xs) childContent (RootedPredTrie T.Text resultContent)+ ( xs' ~ CatMaybes xs+ , Singleton (UrlChunks xs) childContent (RootedPredTrie T.Text resultContent) , ArityTypeListIso childContent xs' resultContent ) @@ -131,7 +135,6 @@ -- by a predicate with 'matchGroup', -- then we would need another level of arity /before/ the @Double@. match :: ( Monad m- , xs' ~ CatMaybes xs , Match xs' xs childContent resultContent ) => UrlChunks xs -- ^ Predicative path to match against -> childContent -- ^ The response to send@@ -172,7 +175,6 @@ -- doing this with a parser or regular expression will necessitate the existing -- arity in the handlers before the progam can compile. matchGroup :: ( Monad m- , xs' ~ CatMaybes xs , MatchGroup xs' xs childContent resultContent childSec resultSec ) => UrlChunks xs -- ^ Predicative path to match against -> RouterT childContent childSec m () -- ^ Child routes to nest@@ -225,8 +227,7 @@ -- with 'routeAuth': -- -- > route routes . routeAuth routes-route :: ( Monad m- , MonadIO m+route :: ( MonadIO m ) => RouterT (MiddlewareT m) sec m a -- ^ The Router -> MiddlewareT m route hs app req resp = do@@ -246,8 +247,7 @@ -- an exception based on the current 'Network.Wai.Middleware.Request' and -- the /layers/ of 'auth' tokens passed in your router, turn your router -- into a 'Control.Monad.guard' for middlewares, basically.-routeAuth :: ( Monad m- , MonadIO m+routeAuth :: ( MonadIO m , MonadThrow m ) => (Request -> [sec] -> m ()) -- ^ authorization method -> RouterT (MiddlewareT m) (SecurityToken sec) m a -- ^ The Router@@ -259,8 +259,7 @@ -- * Extraction ------------------------------- -- | Extracts only the normal 'match', 'matchGroup' and 'matchHere' routes.-extractMatch :: ( Monad m- , MonadIO m+extractMatch :: ( MonadIO m ) => [T.Text] -- ^ The path to match against -> RouterT r sec m a -- ^ The Router -> m (Maybe r)@@ -279,8 +278,7 @@ -- | Extracts only the 'matchAny' responses; something like the greatest-lower-bound.-extractMatchAny :: ( Monad m- , MonadIO m+extractMatchAny :: ( MonadIO m ) => [T.Text] -- ^ The path to match against -> RouterT r sec m a -- ^ The Router -> m (Maybe r)@@ -292,8 +290,7 @@ -- | Find the security tokens / authorization roles affiliated with -- a request for a set of routes.-extractAuthSym :: ( Monad m- , MonadIO m+extractAuthSym :: ( MonadIO m ) => [T.Text] -- ^ The path to match against -> RouterT x (SecurityToken sec) m a -- ^ The Router -> m [sec]@@ -309,8 +306,7 @@ {-# INLINEABLE extractAuthSym #-} -- | Extracts only the security handling logic, and turns it into a guard.-extractAuth :: ( Monad m- , MonadIO m+extractAuth :: ( MonadIO m , MonadThrow m ) => (Request -> [sec] -> m ()) -- ^ authorization method -> Request@@ -327,7 +323,6 @@ -- to the responses based on a /furthest-route-reached/ method, or like a -- greatest-lower-bound. extractNearestVia :: ( MonadIO m- , Monad m ) => [T.Text] -- ^ The path to match against -> (RouterT r sec m a -> m (RootedPredTrie T.Text r)) -> RouterT r sec m a
src/Web/Routes/Nested/Match.hs view
@@ -35,13 +35,13 @@ , UrlChunks ) where -import Prelude hiding (pred)-import Data.Attoparsec.Text-import Text.Regex-import qualified Data.Text as T-import Control.Monad-import Control.Error (hush)-import Data.Trie.Pred+import Prelude hiding (pred)+import Data.Attoparsec.Text (Parser, parseOnly)+import Text.Regex (Regex, matchRegex)+import qualified Data.Text as T+import Control.Monad (guard)+import Control.Error (hush)+import Data.Trie.Pred (PathChunk, PathChunks, pred, nil, only, (./)) o_, origin_ :: UrlChunks '[]
src/Web/Routes/Nested/Types.hs view
@@ -28,19 +28,20 @@ ExtrudeSoundly ) where -import Web.Routes.Nested.Match-import Network.Wai.Middleware.Verbs-import Network.Wai.Middleware.ContentType-import Network.Wai.Trans-import Data.Trie.Pred.Base (RootedPredTrie (..))-import Data.Trie.Pred.Interface.Types (Extrude (..), CatMaybes)+import Web.Routes.Nested.Match (UrlChunks)+import Network.Wai.Middleware.Verbs (VerbListenerT, execVerbListenerT, lookupVerb, getVerb)+import Network.Wai.Middleware.ContentType (FileExtListenerT, fileExtsToMiddleware)+import Network.Wai.Trans (MiddlewareT)+import Data.Trie.Pred.Base (RootedPredTrie (..))+import Data.Trie.Pred.Interface.Types (Extrude (..), CatMaybes) -import Data.Monoid-import qualified Data.Text as T-import Data.Function.Poly-import Data.Singleton.Class (Extractable)-import Control.Monad.Trans-import qualified Control.Monad.State as S+import Data.Monoid ((<>))+import qualified Data.Text as T+import Data.Function.Poly (ArityTypeListIso)+import Data.Singleton.Class (Extractable)+import Control.Monad.Trans (MonadTrans)+import Control.Monad.IO.Class (MonadIO)+import qualified Control.Monad.State as S import Control.Monad.Trans.Control.Aligned (MonadBaseControl) @@ -94,8 +95,7 @@ -- | Run the content builder into a middleware that responds when the content -- is satisfiable (i.e. @Accept@ headers are O.K., etc.)-action :: Monad m- => MonadBaseControl IO m stM+action :: MonadBaseControl IO m stM => Extractable stM => ActionT m () -> MiddlewareT m action xs app req respond = do
test/Test.hs view
@@ -1,9 +1,8 @@ module Main where -import Test.Hspec (hspec) import Spec (spec)-import Test.Tasty-import Test.Tasty.Hspec+import Test.Tasty (defaultMain)+import Test.Tasty.Hspec (testSpec) main :: IO ()
test/Web/Routes/NestedSpec.hs view
@@ -4,10 +4,10 @@ module Web.Routes.NestedSpec (spec) where -import Web.Routes.NestedSpec.Basic+import Web.Routes.NestedSpec.Basic (app) -import Test.Hspec-import Test.Hspec.Wai as HW+import Test.Hspec (Spec, describe, it)+import Test.Hspec.Wai (get, shouldRespondWith, with)
test/Web/Routes/NestedSpec/Basic.hs view
@@ -8,13 +8,13 @@ module Web.Routes.NestedSpec.Basic where -import Web.Routes.Nested-import Network.Wai.Trans-import Network.HTTP.Types-import Text.Regex-import Data.Attoparsec.Text hiding (match)-import Control.Monad.Catch-import GHC.Generics+import Web.Routes.Nested (o_, p_, l_, r_, (</>), match, matchHere, matchGroup, auth, AuthScope (..), textOnly, routeAuth)+import Network.Wai.Trans (Middleware, Application, Request, catchMiddlewareT)+import Network.HTTP.Types (status401, status404, status200)+import Text.Regex (mkRegex)+import Data.Attoparsec.Text (double)+import Control.Monad.Catch (Exception, MonadThrow (throwM))+import GHC.Generics (Generic) data AuthRole = AuthRole deriving (Show, Eq)