wai-routes 0.3.0 → 0.3.1
raw patch · 6 files changed
+114/−29 lines, 6 filesdep +bytestringPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
Dependencies added: bytestring
API changes (from Hackage documentation)
+ Network.Wai.Middleware.Routes.ContentTypes: contentType :: ByteString -> (HeaderName, ByteString)
+ Network.Wai.Middleware.Routes.ContentTypes: typeAtom :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeCss :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeFlv :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeGif :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeHtml :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeJavascript :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeJpeg :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeJson :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeOctet :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeOgv :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typePlain :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typePng :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeRss :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeSvg :: ByteString
+ Network.Wai.Middleware.Routes.ContentTypes: typeXml :: ByteString
- Network.Wai.Middleware.Routes.Routes: type Handler master = master -> App
+ Network.Wai.Middleware.Routes.Routes: type Handler master = master -> RequestData -> ResourceT IO Response
Files
- README +2/−1
- examples/Example.hs +20/−17
- src/Network/Wai/Middleware/Routes/ContentTypes.hs +79/−0
- src/Network/Wai/Middleware/Routes/Monad.hs +2/−2
- src/Network/Wai/Middleware/Routes/Routes.hs +6/−6
- wai-routes.cabal +5/−3
README view
@@ -1,4 +1,4 @@-Wai Routes (wai-routes-0.3.0)+Wai Routes (wai-routes-0.3.1) ============================== This package provides typesafe URLs for Wai applications.@@ -72,4 +72,5 @@ 0.2.3 : Implemented a better showRoute function. Added blaze-builder as a dependency 0.2.4 : Put an upper bound on yesod-routes version as 1.2 breaks API compatibility 0.3.0 : yesod-routes 1.2 compatibility. Abstracted request data. Created `runNext` which skips to the next app in the wai stack+0.3.1 : Removed internal 'App' synonym which only muddied the types. Added common content types for convenience.
examples/Example.hs view
@@ -3,6 +3,7 @@ import Network.Wai import Network.Wai.Middleware.Routes+import Network.Wai.Middleware.Routes.ContentTypes import Network.Wai.Application.Static import Network.Wai.Handler.Warp import Network.HTTP.Types@@ -39,16 +40,19 @@ /skip SkipR GET |] --- Our handlers always produce json-jsonHeaders :: ResponseHeaders-jsonHeaders = [("Content-Type", "application/json")] -- Handlers +-- Standard Json output+jsonOut :: ToJSON a => a -> Response+jsonOut = responseLBS status200 jsonHeaders . encode+ where+ jsonHeaders :: ResponseHeaders+ jsonHeaders = [contentType typeJson]+ -- Display the possible actions getHomeR :: Handler MyRoute-getHomeR _master req = return $ responseLBS status200 jsonHeaders jsonOut- where jsonOut = encode $ M.fromList (+getHomeR _master _req = return $ jsonOut $ M.fromList ( [("description", [["Simple User database Example"]]) ,("links" ,[["home", showRoute HomeR]@@ -63,10 +67,10 @@ getUsersR (MyRoute dbref) _req = do db <- liftIO $ readIORef dbref let dblinks = map linkify db- let jsonOut = encode $ M.fromList (+ let out = M.fromList ( [("description", [["Users List"]]) ,("links", dblinks)] :: [(Text, [[Text]])] )- return $ responseLBS status200 jsonHeaders jsonOut+ return $ jsonOut out where linkify user = [userName user, showRoute $ UserR (userId user) UserRootR] @@ -75,9 +79,9 @@ getUserRootR i (MyRoute dbref) _req = do db <- liftIO $ readIORef dbref case ulookup i db of- Nothing -> return $ responseLBS status200 jsonHeaders $ encode ("ERROR: User not found" :: Text)+ Nothing -> return $ jsonOut ("ERROR: User not found" :: Text) Just user -> do- let jsonOut = encode $ M.fromList (+ let out = M.fromList ( [("description", [["User details"]]) ,("data" ,[["Id", T.pack $ show $ userId user]@@ -91,22 +95,20 @@ ] ) ] :: [(Text, [[Text]])] )- return $ responseLBS status200 jsonHeaders jsonOut+ return $ jsonOut out where ulookup _ [] = Nothing ulookup ui (u:us) = if userId u == ui then Just u else ulookup ui us -- Delete a user: GET getUserDeleteR :: Int -> Handler MyRoute-getUserDeleteR _ _master req = return $ responseLBS status200 jsonHeaders jsonOut+getUserDeleteR _ _master _req = return $ jsonOut err where err = ["DELETE","please use POST"]::[Text]- jsonOut = encode err -- Delete a user: POST postUserDeleteR :: Int -> Handler MyRoute-postUserDeleteR _ _master _req = return $ responseLBS status200 jsonHeaders jsonOut+postUserDeleteR _ _master _req = return $ jsonOut err where err = ["DELETE","not implemented"]::[Text]- jsonOut = encode err -- Demonstrate skipping routes getSkipR :: Handler MyRoute@@ -129,9 +131,8 @@ getSkippedR :: Handler MySkippedRoute getSkippedR _req _master =- return $ responseLBS status200 jsonHeaders jsonOut+ return $ jsonOut err where err = ["SKIPPED","skipped route"]::[Text]- jsonOut = encode err -- The application that uses our route -- NOTE: We use the Route Monad to simplify routing@@ -144,5 +145,7 @@ -- Run the application main :: IO ()-main = toWaiApp application >>= run 8080+main = do+ putStrLn "Starting server on port 8080"+ toWaiApp application >>= run 8080
+ src/Network/Wai/Middleware/Routes/ContentTypes.hs view
@@ -0,0 +1,79 @@+{-# LANGUAGE OverloadedStrings, GeneralizedNewtypeDeriving, TypeFamilies #-}++{- |+Module : Network.Wai.Middleware.Routes.ContentTypes+Copyright : (c) Anupam Jain 2013+License : MIT (see the file LICENSE)++Maintainer : ajnsit@gmail.com+Stability : experimental+Portability : non-portable (uses ghc extensions)++Defines the commonly used content types+-}+module Network.Wai.Middleware.Routes.ContentTypes+ ( -- * Construct content Type+ contentType+ -- * Various common content types+ , typeHtml, typePlain, typeJson+ , typeXml, typeAtom, typeRss+ , typeJpeg, typePng, typeGif+ , typeSvg, typeJavascript, typeCss+ , typeFlv, typeOgv, typeOctet+ )+ where++import Data.ByteString (ByteString)+import Data.ByteString.Char8 () -- Import IsString instance for ByteString+import Network.HTTP.Types.Header (HeaderName())++-- | Creates a content type header+-- Ready to be passed to `responseLBS`+contentType :: ByteString -> (HeaderName, ByteString)+contentType typ = ("Content-Type", typ)++typeHtml :: ByteString+typeHtml = "text/html; charset=utf-8"++typePlain :: ByteString+typePlain = "text/plain; charset=utf-8"++typeJson :: ByteString+typeJson = "application/json; charset=utf-8"++typeXml :: ByteString+typeXml = "text/xml"++typeAtom :: ByteString+typeAtom = "application/atom+xml"++typeRss :: ByteString+typeRss = "application/rss+xml"++typeJpeg :: ByteString+typeJpeg = "image/jpeg"++typePng :: ByteString+typePng = "image/png"++typeGif :: ByteString+typeGif = "image/gif"++typeSvg :: ByteString+typeSvg = "image/svg+xml"++typeJavascript :: ByteString+typeJavascript = "text/javascript; charset=utf-8"++typeCss :: ByteString+typeCss = "text/css; charset=utf-8"++typeFlv :: ByteString+typeFlv = "video/x-flv"++typeOgv :: ByteString+typeOgv = "video/ogg"++typeOctet :: ByteString+typeOctet = "application/octet-stream"+
src/Network/Wai/Middleware/Routes/Monad.hs view
@@ -46,7 +46,7 @@ setDefaultApp :: Application -> RouteState -> RouteState setDefaultApp a s = s {defaultApp=a} --- ! The Route Monad+-- | The Route Monad newtype RouteM a = S { runS :: StateT RouteState IO a } deriving (Monad, MonadIO, Functor, MonadState RouteState) @@ -60,7 +60,7 @@ route :: (Routable master) => master -> RouteM () route = middleware . routeDispatch --- ! Set the default action of the Application.+-- | Set the default action of the Application. -- You should only call this once in an application. -- Subsequent invocations override the previous settings. defaultAction :: Application -> RouteM ()
src/Network/Wai/Middleware/Routes/Routes.hs view
@@ -71,6 +71,9 @@ import Control.Arrow (second) import Data.Maybe (fromMaybe) +-- Common ContentTypes+import Network.Wai.Middleware.Routes.ContentTypes+ -- An abstract request data RequestData = RequestData { waiReq :: Request@@ -81,11 +84,8 @@ runNext :: RequestData -> ResourceT IO Response runNext req = nextApp req $ waiReq req --- Internal data type for convenience-type App = RequestData -> ResourceT IO Response- -- | A `Handler` generates an App from the master datatype-type Handler master = master -> App+type Handler master = master -> RequestData -> ResourceT IO Response -- Baked in applications that handle 404 and 405 errors -- TODO: Inspect the request to figure out acceptable output formats@@ -94,7 +94,7 @@ app404 _master req = nextApp req $ waiReq req app405 :: Handler master-app405 _master _req = return $ ResponseBuilder status405 [("Content-Type","text/plain")] $ fromByteString "405 - Method Not Allowed"+app405 _master _req = return $ ResponseBuilder status405 [contentType typePlain] $ fromByteString "405 - Method Not Allowed" -- | Generates all the things needed for efficient routing, -- including your application's `Route` datatype, and@@ -131,7 +131,7 @@ :: Handler master -> master -> Maybe (Route master)- -> App+ -> RequestData -> ResourceT IO Response -- App runHandler h master _ = h master -- | A `Routable` instance can be used in dispatching.
wai-routes.cabal view
@@ -1,5 +1,5 @@ Name: wai-routes-Version: 0.3.0+Version: 0.3.1 Synopsis: Typesafe URLs for Wai applications. Homepage: https://github.com/ajnsit/wai-routes License: MIT@@ -63,8 +63,8 @@ source-repository this type: git- location: http://github.com/ajnsit/wai-routes/tree/v0.3.0- tag: v0.3.0+ location: http://github.com/ajnsit/wai-routes/tree/v0.3.1+ tag: v0.3.1 Library hs-source-dirs: src@@ -73,6 +73,7 @@ , conduit >= 0.5 && < 1.1 , path-pieces , text+ , bytestring , http-types >= 0.7 , blaze-builder >= 0.2.1.4 && < 0.4 , template-haskell@@ -81,4 +82,5 @@ exposed-modules: Network.Wai.Middleware.Routes , Network.Wai.Middleware.Routes.Routes , Network.Wai.Middleware.Routes.Monad+ , Network.Wai.Middleware.Routes.ContentTypes