packages feed

wai-middleware-verbs 0.1.0 → 0.1.1

raw patch · 3 files changed

+137/−17 lines, 3 filesdep +hashabledep +textdep +unordered-containersdep −containersnew-component:exe:examplePVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: hashable, text, unordered-containers, wai-middleware-content-type, warp

Dependencies removed: containers

API changes (from Hackage documentation)

+ Network.Wai.Middleware.Verbs: instance Data.Hashable.Class.Hashable Network.Wai.Middleware.Verbs.Verb
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Constructor Network.Wai.Middleware.Verbs.C1_0StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Constructor Network.Wai.Middleware.Verbs.C1_1StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Constructor Network.Wai.Middleware.Verbs.C1_2StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Constructor Network.Wai.Middleware.Verbs.C1_3StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Constructor Network.Wai.Middleware.Verbs.C1_4StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Constructor Network.Wai.Middleware.Verbs.C1_5StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Constructor Network.Wai.Middleware.Verbs.C1_6StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Constructor Network.Wai.Middleware.Verbs.C1_7StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Constructor Network.Wai.Middleware.Verbs.C1_8StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Datatype Network.Wai.Middleware.Verbs.D1StdMethod
+ Network.Wai.Middleware.Verbs: instance GHC.Generics.Generic Network.HTTP.Types.Method.StdMethod
- Network.Wai.Middleware.Verbs: type VerbMap m r = Map Verb (Request -> m (), r)
+ Network.Wai.Middleware.Verbs: type VerbMap m r = HashMap Verb (Request -> m (), r)

Files

+ examples/Example.hs view
@@ -0,0 +1,61 @@+{-# LANGUAGE+    OverloadedStrings+  , DeriveDataTypeable+  #-}++module Main where++import Network.Wai.Handler.Warp+import Network.Wai.Middleware.Verbs+import Network.Wai.Middleware.ContentType (textOnly)+import Network.Wai.Trans+import qualified Data.Text.Lazy as LT+import Data.Monoid+import Data.Typeable+import Control.Monad.IO.Class+import Control.Monad.Catch+++theEmbeddedApp :: MonadIO m => LT.Text -> MiddlewareT m+theEmbeddedApp v _ _ respond =+  respond $ textOnly $ v <> " Verb accepted!"+++data UploadError = UploadFailed+  deriving (Show, Typeable)++instance Exception UploadError++myListener :: ( MonadIO m+              , MonadThrow m+              ) => VerbListenerT (MiddlewareT m) m ()+myListener = do+  get                $ theEmbeddedApp "GET"+  put  uploadFail    $ theEmbeddedApp "PUT" -- should never work+  post uploadSucceed $ theEmbeddedApp "POST"+  delete             $ theEmbeddedApp "DELETE"+  where+    uploadFail    _ = throwM UploadFailed+    uploadSucceed _ = return ()++handleError :: UploadError -> MiddlewareT m+handleError UploadFailed _ _ respond =+  respond $ textOnly "Upload Failed!"+++myApp :: ( MonadIO m+         , MonadCatch m+         ) => MiddlewareT m+myApp app req respond =+          (verbsToMiddleware myListener app req respond)+  `catch` (\e -> handleError e app req respond)+++main :: IO ()+main = run 3000 (myApp defApp)+  where+    defApp :: Application+    defApp _ respond =+      respond $ textOnly "404"++
src/Network/Wai/Middleware/Verbs.hs view
@@ -6,6 +6,8 @@   , MultiParamTypeClasses   , UndecidableInstances   , GeneralizedNewtypeDeriving+  , DeriveGeneric+  , TypeSynonymInstances   #-}  {-|@@ -56,9 +58,10 @@ import           Network.Wai.Trans import           Network.HTTP.Types -import           Data.Map (Map)-import qualified Data.Map                             as Map+import           Data.HashMap.Lazy (HashMap)+import qualified Data.HashMap.Lazy                    as HM import           Data.Monoid+import           Data.Hashable import           Control.Arrow (second) import           Control.Applicative import           Control.Monad.Trans@@ -75,17 +78,24 @@ import           Control.Monad.Logger import           Control.Error +import           GHC.Generics + -- * Types  -- | A map from an HTTP verb, to a result and uploading method.-type VerbMap m r = Map Verb (Request -> m (), r)+type VerbMap m r = HashMap Verb (Request -> m (), r)  type Verb = StdMethod +deriving instance Generic Verb++instance Hashable Verb++ -- | Fetches the HTTP verb from the WAI @Request@ - defaults to GET. getVerb :: Request -> Verb-getVerb req = fromMaybe GET $ httpMethodToMSym $ requestMethod req+getVerb req = fromMaybe GET $ httpMethodToMSym (requestMethod req)   where     httpMethodToMSym :: Method -> Maybe Verb     httpMethodToMSym x | x == methodGet    = Just GET@@ -94,13 +104,16 @@                        | x == methodDelete = Just DELETE                        | otherwise         = Nothing +{-# INLINEABLE getVerb #-}+ -- | Take the monadic partial result of @lookupVerb@, and actually h the upload. lookupVerb :: Monad m => Request -> Verb -> VerbMap m r -> m (Maybe r) lookupVerb req v vmap = runMaybeT $ do-  (upload, result) <- hoistMaybe $ Map.lookup v vmap+  (upload, result) <- hoistMaybe $ HM.lookup v vmap   lift (upload req)   return result +{-# INLINEABLE lookupVerb #-}  -- * Verb Writer @@ -115,9 +128,9 @@ --   >     uploader :: MonadIO Request -> m () --   >     uploader req = --   >       liftIO $ print =<< strictRequestBody req-newtype VerbListenerT r m a =-  VerbListenerT { runVerbListenerT :: StateT (VerbMap m r) m a }-    deriving ( Functor, Applicative, Alternative, Monad, MonadFix, MonadPlus+newtype VerbListenerT r m a = VerbListenerT+  { runVerbListenerT :: StateT (VerbMap m r) m a+  } deriving ( Functor, Applicative, Alternative, Monad, MonadFix, MonadPlus              , MonadState (VerbMap m r), MonadWriter w, MonadReader r, MonadIO              , MonadError e', MonadCont, MonadBase b, MonadThrow, MonadCatch              , MonadMask, MonadLogger@@ -128,6 +141,7 @@ execVerbListenerT :: Monad m => VerbListenerT r m a -> m (VerbMap m r) execVerbListenerT xs = execStateT (runVerbListenerT xs) mempty +{-# INLINEABLE execVerbListenerT #-}  instance MonadTrans (VerbListenerT r) where   lift = VerbListenerT . lift -- uses StateT@@ -144,48 +158,58 @@   fromMaybe (app req respond) $     (\mid -> mid app req respond) <$> mMiddleware +{-# INLINEABLE verbsToMiddleware #-}  -- * Combinators  -- | For simple @GET@ responses get :: ( Monad m        ) => r -> VerbListenerT r m ()-get r = tell' $ Map.singleton GET ( const $ return ()+get r = tell' $! HM.singleton GET ( const $ return ()                                   , r                                   ) +{-# INLINEABLE get #-}+ -- | For simple @POST@ responses post :: ( Monad m         ) => (Request -> m ()) -- Handle upload           -> r           -> VerbListenerT r m ()-post h r = tell' $ Map.singleton POST ( h+post h r = tell' $! HM.singleton POST ( h                                       , r                                       ) +{-# INLINEABLE post #-}+ -- | For simple @PUT@ responses put :: ( Monad m        ) => (Request -> m ()) -- Handle upload          -> r          -> VerbListenerT r m ()-put h r = tell' $ Map.singleton PUT ( h+put h r = tell' $! HM.singleton PUT ( h                                     , r                                     ) +{-# INLINEABLE put #-}+ -- | For simple @DELETE@ responses delete :: ( Monad m           ) => r -> VerbListenerT r m ()-delete r = tell' $ Map.singleton DELETE ( const $ return ()+delete r = tell' $! HM.singleton DELETE ( const $ return ()                                         , r                                         ) +{-# INLINEABLE delete #-}  tell' :: (Monoid w, MonadState w m) => w -> m ()-tell' x = do-  xs <- S.get-  S.put $ xs <> x+tell' x = modify' (<> x) +{-# INLINEABLE tell' #-}+ mapVerbs :: Monad m => (r -> s) ->  VerbListenerT r m () -> VerbListenerT s m () mapVerbs f xs = do   vmap <- lift $ execVerbListenerT xs   tell' $ second f <$> vmap++{-# INLINEABLE mapVerbs #-}
wai-middleware-verbs.cabal view
@@ -1,5 +1,5 @@ Name:                   wai-middleware-verbs-Version:                0.1.0+Version:                0.1.1 Author:                 Athan Clark <athan.clark@gmail.com> Maintainer:             Athan Clark <athan.clark@gmail.com> License:                BSD3@@ -10,15 +10,19 @@ Build-Type:             Simple Category:               Web +Flag Example+  Description:          Build a simple example+  Default:              False+ Library   Default-Language:     Haskell2010   HS-Source-Dirs:       src   GHC-Options:          -Wall   Exposed-Modules:      Network.Wai.Middleware.Verbs   Build-Depends:        base >= 4.8 && < 5-                      , containers                       , exceptions                       , errors+                      , hashable                       , http-types                       , monad-logger                       , mmorph@@ -26,8 +30,39 @@                       , resourcet                       , transformers                       , transformers-base+                      , unordered-containers                       , wai                       , wai-transformers >= 0.0.3++Executable example+  if flag(Example)+    Buildable: True+  else+    Buildable: False+  Default-Language:     Haskell2010+  HS-Source-Dirs:       src+                      , examples+  GHC-Options:          -Wall+  Main-Is:              Example.hs+  Other-Modules:        Network.Wai.Middleware.Verbs+  Build-Depends:        base >= 4.8 && < 5+                      , exceptions+                      , errors+                      , hashable+                      , http-types+                      , monad-logger+                      , mmorph+                      , mtl+                      , resourcet+                      , text+                      , transformers+                      , transformers-base+                      , unordered-containers+                      , wai+                      , wai-transformers >= 0.0.3+                      , wai-middleware-content-type+                      , warp+    Source-Repository head   Type:                 git