add client, server and docs support for the DELETE HTTP method
This commit is contained in:
parent
4ebc4944c2
commit
97d4133eb1
6 changed files with 75 additions and 3 deletions
|
@ -34,6 +34,9 @@ instance ToJSON Greet
|
||||||
instance ToCapture (Capture "name" Text) where
|
instance ToCapture (Capture "name" Text) where
|
||||||
toCapture _ = DocCapture "name" "name of the person to greet"
|
toCapture _ = DocCapture "name" "name of the person to greet"
|
||||||
|
|
||||||
|
instance ToCapture (Capture "greetid" Text) where
|
||||||
|
toCapture _ = DocCapture "greetid" "identifier of the greet msg to remove"
|
||||||
|
|
||||||
instance ToParam (GetParam "capital" Bool) where
|
instance ToParam (GetParam "capital" Bool) where
|
||||||
toParam _ =
|
toParam _ =
|
||||||
DocGetParam "capital"
|
DocGetParam "capital"
|
||||||
|
@ -49,13 +52,14 @@ instance ToSample Greet where
|
||||||
type TestApi =
|
type TestApi =
|
||||||
"hello" :> Capture "name" Text :> GetParam "capital" Bool :> Get Greet
|
"hello" :> Capture "name" Text :> GetParam "capital" Bool :> Get Greet
|
||||||
:<|> "greet" :> RQBody Greet :> Post Greet
|
:<|> "greet" :> RQBody Greet :> Post Greet
|
||||||
|
:<|> "delete" :> Capture "greetid" Text :> Delete
|
||||||
|
|
||||||
testApi :: Proxy TestApi
|
testApi :: Proxy TestApi
|
||||||
testApi = Proxy
|
testApi = Proxy
|
||||||
|
|
||||||
-- Server-side handlers
|
-- Server-side handlers
|
||||||
server :: Server TestApi
|
server :: Server TestApi
|
||||||
server = hello :<|> greet
|
server = hello :<|> greet :<|> delete
|
||||||
|
|
||||||
where hello name Nothing = hello name (Just False)
|
where hello name Nothing = hello name (Just False)
|
||||||
hello name (Just False) = return . Greet $ "Hello, " <> name
|
hello name (Just False) = return . Greet $ "Hello, " <> name
|
||||||
|
@ -63,18 +67,22 @@ server = hello :<|> greet
|
||||||
|
|
||||||
greet = return
|
greet = return
|
||||||
|
|
||||||
|
delete _ = return ()
|
||||||
|
|
||||||
-- Client-side query functions
|
-- Client-side query functions
|
||||||
clientApi :: Client TestApi
|
clientApi :: Client TestApi
|
||||||
clientApi = client testApi
|
clientApi = client testApi
|
||||||
|
|
||||||
getGreet :: Text -> Maybe Bool -> URI -> EitherT String IO Greet
|
getGreet :: Text -> Maybe Bool -> URI -> EitherT String IO Greet
|
||||||
postGreet :: Greet -> URI -> EitherT String IO Greet
|
postGreet :: Greet -> URI -> EitherT String IO Greet
|
||||||
getGreet :<|> postGreet = clientApi
|
deleteGreet :: Text -> URI -> EitherT String IO ()
|
||||||
|
getGreet :<|> postGreet :<|> deleteGreet = clientApi
|
||||||
|
|
||||||
-- Turn the server into a WAI app
|
-- Turn the server into a WAI app
|
||||||
test :: Application
|
test :: Application
|
||||||
test = serve testApi server
|
test = serve testApi server
|
||||||
|
|
||||||
|
-- Documentation
|
||||||
docsGreet :: API
|
docsGreet :: API
|
||||||
docsGreet = docs testApi
|
docsGreet = docs testApi
|
||||||
|
|
||||||
|
@ -91,6 +99,7 @@ main = do
|
||||||
print =<< runEitherT (getGreet "alp" (Just False) uri)
|
print =<< runEitherT (getGreet "alp" (Just False) uri)
|
||||||
let g = Greet "yo"
|
let g = Greet "yo"
|
||||||
print =<< runEitherT (postGreet g uri)
|
print =<< runEitherT (postGreet g uri)
|
||||||
|
print =<< runEitherT (deleteGreet "blah" uri)
|
||||||
killThread tid
|
killThread tid
|
||||||
putStrLn "\n---------\n"
|
putStrLn "\n---------\n"
|
||||||
printMarkdown docsGreet
|
printMarkdown docsGreet
|
||||||
|
|
|
@ -21,6 +21,7 @@ library
|
||||||
Servant.Text
|
Servant.Text
|
||||||
Servant.API
|
Servant.API
|
||||||
Servant.API.Capture
|
Servant.API.Capture
|
||||||
|
Servant.API.Delete
|
||||||
Servant.API.Get
|
Servant.API.Get
|
||||||
Servant.API.GetParam
|
Servant.API.GetParam
|
||||||
Servant.API.Post
|
Servant.API.Post
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
module Servant
|
module Servant
|
||||||
( module Servant.API
|
( module Servant.API
|
||||||
, module Servant.Client
|
, module Servant.Client
|
||||||
|
, module Servant.Docs
|
||||||
, module Servant.Server
|
, module Servant.Server
|
||||||
, module Servant.Text
|
, module Servant.Text
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Servant.API
|
import Servant.API
|
||||||
import Servant.Client
|
import Servant.Client
|
||||||
|
import Servant.Docs
|
||||||
import Servant.Server
|
import Servant.Server
|
||||||
import Servant.Text
|
import Servant.Text
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
module Servant.API
|
module Servant.API
|
||||||
( module Servant.API.Capture
|
( module Servant.API.Capture
|
||||||
|
, module Servant.API.Delete
|
||||||
, module Servant.API.Get
|
, module Servant.API.Get
|
||||||
, module Servant.API.GetParam
|
, module Servant.API.GetParam
|
||||||
, module Servant.API.Post
|
, module Servant.API.Post
|
||||||
|
@ -9,6 +10,7 @@ module Servant.API
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Servant.API.Capture
|
import Servant.API.Capture
|
||||||
|
import Servant.API.Delete
|
||||||
import Servant.API.Get
|
import Servant.API.Get
|
||||||
import Servant.API.GetParam
|
import Servant.API.GetParam
|
||||||
import Servant.API.Post
|
import Servant.API.Post
|
||||||
|
|
58
src/Servant/API/Delete.hs
Normal file
58
src/Servant/API/Delete.hs
Normal file
|
@ -0,0 +1,58 @@
|
||||||
|
{-# LANGUAGE TypeFamilies #-}
|
||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
{-# LANGUAGE ScopedTypeVariables #-}
|
||||||
|
module Servant.API.Delete where
|
||||||
|
|
||||||
|
import Control.Monad
|
||||||
|
import Control.Monad.IO.Class
|
||||||
|
import Control.Monad.Trans.Either
|
||||||
|
import Data.Proxy
|
||||||
|
import Data.String.Conversions
|
||||||
|
import Network.HTTP.Types
|
||||||
|
import Network.URI
|
||||||
|
import Network.Wai
|
||||||
|
import Servant.Client
|
||||||
|
import Servant.Docs
|
||||||
|
import Servant.Server
|
||||||
|
|
||||||
|
import qualified Network.HTTP.Client as Client
|
||||||
|
|
||||||
|
-- | Endpoint for DELETE requests.
|
||||||
|
data Delete
|
||||||
|
|
||||||
|
instance HasServer Delete where
|
||||||
|
type Server Delete = EitherT (Int, String) IO ()
|
||||||
|
|
||||||
|
route Proxy action _globalPathInfo request respond
|
||||||
|
| null (pathInfo request) && requestMethod request == methodDelete = do
|
||||||
|
e <- runEitherT action
|
||||||
|
respond $ Just $ case e of
|
||||||
|
Right () ->
|
||||||
|
responseLBS status204 [] ""
|
||||||
|
Left (status, message) ->
|
||||||
|
responseLBS (mkStatus status (cs message)) [] (cs message)
|
||||||
|
| otherwise = respond Nothing
|
||||||
|
|
||||||
|
instance HasClient Delete where
|
||||||
|
type Client Delete = URI -> EitherT String IO ()
|
||||||
|
|
||||||
|
clientWithRoute Proxy req uri = do
|
||||||
|
partialRequest <- liftIO $ reqToRequest req uri
|
||||||
|
|
||||||
|
let request = partialRequest { Client.method = methodDelete
|
||||||
|
}
|
||||||
|
|
||||||
|
innerResponse <- liftIO . __withGlobalManager $ \ manager ->
|
||||||
|
Client.httpLbs request manager
|
||||||
|
|
||||||
|
when (Client.responseStatus innerResponse /= status204) $
|
||||||
|
left ("HTTP DELETE request failed with status: " ++ show (Client.responseStatus innerResponse))
|
||||||
|
|
||||||
|
instance HasDocs Delete where
|
||||||
|
docsFor Proxy (endpoint, action) =
|
||||||
|
single endpoint' action'
|
||||||
|
|
||||||
|
where endpoint' = endpoint & method .~ DocDELETE
|
||||||
|
|
||||||
|
action' = action & response.respBody .~ Nothing
|
||||||
|
& response.respStatus .~ 204
|
|
@ -398,6 +398,6 @@ printMarkdown = imapM_ printEndpoint
|
||||||
putStrLn $ ""
|
putStrLn $ ""
|
||||||
putStrLn $ " - Status code " ++ show (resp ^. respStatus)
|
putStrLn $ " - Status code " ++ show (resp ^. respStatus)
|
||||||
resp ^. respBody &
|
resp ^. respBody &
|
||||||
maybe (putStrLn " - No response body")
|
maybe (putStrLn " - No response body\n")
|
||||||
(\b -> putStrLn " - Response body as below." >> jsonStr b)
|
(\b -> putStrLn " - Response body as below." >> jsonStr b)
|
||||||
|
|
Loading…
Reference in a new issue